diff --git a/bundles/org.codechecker.eclipse.plugin/build.properties b/bundles/org.codechecker.eclipse.plugin/build.properties index 44ad5f18..0ef59e52 100644 --- a/bundles/org.codechecker.eclipse.plugin/build.properties +++ b/bundles/org.codechecker.eclipse.plugin/build.properties @@ -5,5 +5,6 @@ bin.includes = plugin.xml,\ .,\ icons/,\ contexts.xml,\ - log4j.properties + log4j.properties,\ + resources/ diff --git a/bundles/org.codechecker.eclipse.plugin/pom.xml b/bundles/org.codechecker.eclipse.plugin/pom.xml new file mode 100644 index 00000000..0bb96d5e --- /dev/null +++ b/bundles/org.codechecker.eclipse.plugin/pom.xml @@ -0,0 +1,35 @@ + + + 4.0.0 + + org.codechecker.eclipse + org.codechecker.eclipse.bundles + 1.0.0-SNAPSHOT + + + org.codechecker.eclipse.plugin + 0.0.6-SNAPSHOT + eclipse-plugin + + + empty + 0 + ${project.version} + + + + + + resources + resources + true + + **/*.properties + + + + + + diff --git a/bundles/org.codechecker.eclipse.plugin/resources/config.properties b/bundles/org.codechecker.eclipse.plugin/resources/config.properties new file mode 100644 index 00000000..faca1a5b --- /dev/null +++ b/bundles/org.codechecker.eclipse.plugin/resources/config.properties @@ -0,0 +1,3 @@ +host=${host.log} +port=${port.log} +version=${plugin.version} diff --git a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/init/StartupJob.java b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/init/StartupJob.java index 85192bcc..25aa3d01 100644 --- a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/init/StartupJob.java +++ b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/init/StartupJob.java @@ -3,6 +3,19 @@ import java.util.HashSet; import java.util.Set; +import org.codechecker.eclipse.plugin.CodeCheckerNature; +import org.codechecker.eclipse.plugin.ExternalLogger; +import org.codechecker.eclipse.plugin.Logger; +import org.codechecker.eclipse.plugin.config.CodeCheckerContext; +import org.codechecker.eclipse.plugin.config.global.CcGlobalConfiguration; +import org.codechecker.eclipse.plugin.config.project.CodeCheckerProject; +import org.codechecker.eclipse.plugin.report.job.AnalyzeJob; +import org.codechecker.eclipse.plugin.report.job.JobDoneChangeListener; +import org.codechecker.eclipse.plugin.report.job.PlistParseJob; +import org.codechecker.eclipse.plugin.runtime.SLogger; +import org.codechecker.eclipse.plugin.usage.StatisticUploader; +import org.codechecker.eclipse.plugin.usage.UsageInfo; +import org.codechecker.eclipse.plugin.usage.UsageInfo.CommandType; import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; @@ -24,18 +37,6 @@ import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.PlatformUI; -import org.codechecker.eclipse.plugin.CodeCheckerNature; -import org.codechecker.eclipse.plugin.ExternalLogger; -import org.codechecker.eclipse.plugin.Logger; -import org.codechecker.eclipse.plugin.config.CcConfiguration; -import org.codechecker.eclipse.plugin.config.CodeCheckerContext; -import org.codechecker.eclipse.plugin.config.global.CcGlobalConfiguration; -import org.codechecker.eclipse.plugin.config.project.CodeCheckerProject; -import org.codechecker.eclipse.plugin.report.job.AnalyzeJob; -import org.codechecker.eclipse.plugin.report.job.JobDoneChangeListener; -import org.codechecker.eclipse.plugin.report.job.PlistParseJob; -import org.codechecker.eclipse.plugin.runtime.SLogger; - /** * This eclipse job is responsible for registering the Build listener. * @@ -83,6 +84,8 @@ public IStatus runInUIThread(IProgressMonitor monitor) { Logger.log(IStatus.INFO, Logger.getStackTrace(e)); } + new Thread(new StatisticUploader(new UsageInfo(CommandType.started, null))).run(); + Logger.log(IStatus.INFO, "adding addResourceChangeListener "); ResourcesPlugin.getWorkspace().addResourceChangeListener(new ResourceChangeListener(), IResourceChangeEvent.POST_BUILD | IResourceChangeEvent.POST_CHANGE | diff --git a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/usage/StatisticUploader.java b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/usage/StatisticUploader.java new file mode 100644 index 00000000..a71a27b7 --- /dev/null +++ b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/usage/StatisticUploader.java @@ -0,0 +1,74 @@ +package org.codechecker.eclipse.plugin.usage; + +import java.io.IOException; +import java.io.InputStream; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.Inet4Address; +import java.util.Properties; + +import org.eclipse.core.runtime.FileLocator; +import org.eclipse.core.runtime.Path; +import org.osgi.framework.FrameworkUtil; + +import com.google.gson.Gson; + +/** + * Class for uploading the usage statistics. + */ +public class StatisticUploader implements Runnable { + + private Integer port; + private String host; + private UsageInfo info; + + /** + * Need to pass an {@link UsageInfo}. + * + * @param info + * This will be uploaded in JSON format. + */ + public StatisticUploader(UsageInfo info) { + this.info = info; + } + + /** + * This is the upload logic. The host and port is specified compile time in + * maven. + */ + private void uploadStatistics() { + try (InputStream is = FileLocator.openStream(FrameworkUtil.getBundle(getClass()), + new Path("resources/config.properties"), false)) { + Properties prop = new Properties(); + prop.load(is); + host = prop.getProperty("host"); + try { + port = Integer.parseInt(prop.getProperty("port")); + } catch (Exception e) { + ; + } + } catch (IOException e1) { + ; + } + + try (DatagramSocket socket = new DatagramSocket()) { + if (port != null && host != null) { + DatagramPacket packet = new DatagramPacket(new Gson().toJson(info).getBytes(), + new Gson().toJson(info).getBytes().length, + Inet4Address.getByName(host), port); + socket.send(packet); + } + } catch (IOException e) { + ; + } + } + + /** + * Uploads usage statistics. + */ + @Override + public void run() { + uploadStatistics(); + } + +} diff --git a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/usage/UsageInfo.java b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/usage/UsageInfo.java new file mode 100644 index 00000000..55f7197d --- /dev/null +++ b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/usage/UsageInfo.java @@ -0,0 +1,118 @@ +package org.codechecker.eclipse.plugin.usage; + +import java.io.IOException; +import java.io.InputStream; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.Properties; + +import org.eclipse.core.runtime.FileLocator; +import org.eclipse.core.runtime.IContributor; +import org.eclipse.core.runtime.IExtension; +import org.eclipse.core.runtime.IExtensionPoint; +import org.eclipse.core.runtime.IExtensionRegistry; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Platform; +import org.eclipse.jdt.annotation.Nullable; +import org.osgi.framework.Bundle; +import org.osgi.framework.FrameworkUtil; + +/** + * Class for Storing usage logging related info. + */ +public class UsageInfo { + private static final String UNKNOWN = "unknown"; + private static final String UNKNOWN_VER = "unknown version"; + + @SuppressWarnings("unused") + private String machine = UNKNOWN; + @SuppressWarnings("unused") + private String hostname = UNKNOWN; + //@SuppressWarnings("unused") + //private String clangsa = UNKNOWN; + @SuppressWarnings("unused") + private String version = UNKNOWN_VER; + // TODO make this parameter dynamic, from build parameters. + @SuppressWarnings("unused") + private String pluginVersion = UNKNOWN_VER; + @SuppressWarnings("unused") + private String user = UNKNOWN; + @SuppressWarnings("unused") + private CommandType command_type; + //@SuppressWarnings("unused") + //private String clang_tidy = UNKNOWN; + + /** + * Specify the event type and the CodeChecker version if in context. + * + * @param ct + * The command (event) type to be logged. + * @param ccVersion + * The CodeChecker version to be logged. Not every context has + * CodeChecker. + */ + public UsageInfo(CommandType ct, @Nullable String ccVersion) { + StringBuilder tempos = new StringBuilder(System.getProperty("os.name")); + tempos.append(" ").append(System.getProperty("os.version")); + tempos.append(" / Eclipse ").append(getEclipseVersion()); + machine = tempos.toString(); + try { + hostname = InetAddress.getLocalHost().getHostName(); + } catch (UnknownHostException ex) { + ; + } + if (ccVersion != null) + version = ccVersion; + setPluginVersion(); + user = System.getProperty("user.name"); + command_type = ct; + } + + /** + * Used for returning the eclipse version number. From: + * https://stackoverflow.com/a/28855362/8149485 + * + * @return The eclipse version number in 1.2.3.v19700101-0000 format. + */ + private String getEclipseVersion() { + String version = UNKNOWN_VER; + String product = System.getProperty("eclipse.product"); + IExtensionRegistry registry = Platform.getExtensionRegistry(); + IExtensionPoint point = registry.getExtensionPoint("org.eclipse.core.runtime.products"); + if (point != null) { + IExtension[] extensions = point.getExtensions(); + for (IExtension ext : extensions) + if (product.equals(ext.getUniqueIdentifier())) { + IContributor contributor = ext.getContributor(); + if (contributor != null) { + Bundle bundle = Platform.getBundle(contributor.getName()); + if (bundle != null) + version = bundle.getVersion().toString(); + } + } + } + return version; + } + + /** + * Sets the plugin version from a properties file, which gets substituted during + * build. + */ + private void setPluginVersion() { + try (InputStream is = FileLocator.openStream(FrameworkUtil.getBundle(getClass()), + new Path("resources/config.properties"), false)) { + Properties prop = new Properties(); + prop.load(is); + pluginVersion = prop.getProperty("version"); + } catch (IOException e1) { + e1.printStackTrace(); + } + } + + /** + * Command (Event) types. + */ + public enum CommandType { + started, analyze_started + } +} diff --git a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/usage/package-info.java b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/usage/package-info.java new file mode 100644 index 00000000..da382658 --- /dev/null +++ b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/usage/package-info.java @@ -0,0 +1,4 @@ +/** + * Usage logging. + */ +package org.codechecker.eclipse.plugin.usage; \ No newline at end of file