From a2a8032b426e8019167d60de41e40ddb67f84a0d Mon Sep 17 00:00:00 2001 From: y4zhang Date: Tue, 11 Jul 2017 15:22:40 -0500 Subject: [PATCH 1/8] add uuid to configuration --- drjava/src/edu/rice/cs/drjava/DrJava.java | 9 ++++++++- .../src/edu/rice/cs/drjava/config/OptionConstants.java | 3 +++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/drjava/src/edu/rice/cs/drjava/DrJava.java b/drjava/src/edu/rice/cs/drjava/DrJava.java index c93eb4dc4..f1f37315a 100644 --- a/drjava/src/edu/rice/cs/drjava/DrJava.java +++ b/drjava/src/edu/rice/cs/drjava/DrJava.java @@ -250,6 +250,7 @@ public static void main(final String[] args) { public static void configureAndLoadDrJavaRoot(String[] args) { try { +System.out.println("r"); // if there were files passed on the command line, // try to open them in an existing instance if (!_forceNewInstance && @@ -265,6 +266,7 @@ public static void configureAndLoadDrJavaRoot(String[] args) { int failCount = 0; while(failCount < 2) { // Restart if there are custom JVM args +System.out.println("y"); String masterMemory = getConfig().getSetting(MASTER_JVM_XMX).trim(); boolean _doRestart = (getConfig().getSetting(MASTER_JVM_ARGS).length() > 0) || (!"".equals(masterMemory) && !OptionConstants.heapSizeChoices.get(0).equals(masterMemory)); @@ -286,7 +288,8 @@ public static void configureAndLoadDrJavaRoot(String[] args) { clearFilesToOpen(); _log.log("_filesToOpen copied into class arguments, clearing _filesToOpen"); } - + /*not use +*/ if (_doRestart) { if (DrJava.getConfig().getSetting(OptionConstants.REMOTE_CONTROL_ENABLED)) { // at this time, OUR remote control server hasn't been started yet @@ -299,6 +302,7 @@ public static void configureAndLoadDrJavaRoot(String[] args) { // Run a new copy of DrJava and exit try { +//System.out.println("rrr"); boolean failed = false; JVMBuilder jvmb = JVMBuilder.DEFAULT.jvmArguments(_jvmArgs); @@ -314,6 +318,7 @@ public static void configureAndLoadDrJavaRoot(String[] args) { // start new DrJava Process p = jvmb.start(DrJavaRoot.class.getName(), classArgs); +// System.out.println("yy"); _alreadyRestarted = true; _log.log("_alreadyRestarted = true"); DelayedInterrupter timeout = new DelayedInterrupter(WAIT_BEFORE_DECLARING_SUCCESS); @@ -370,6 +375,8 @@ public static void configureAndLoadDrJavaRoot(String[] args) { } else { +System.out.println("yy!"); +//System.out.println(DrJava.getConfig().getSetting(OptionConstants.UUID)); // No restart -- just invoke DrJavaRoot.main. DrJavaRoot.main(classArgs.toArray(new String[0])); // when we return from here, DrJavaRoot._mainFrame has been initialized diff --git a/drjava/src/edu/rice/cs/drjava/config/OptionConstants.java b/drjava/src/edu/rice/cs/drjava/config/OptionConstants.java index 50e894a0e..0eb62f7f6 100644 --- a/drjava/src/edu/rice/cs/drjava/config/OptionConstants.java +++ b/drjava/src/edu/rice/cs/drjava/config/OptionConstants.java @@ -68,6 +68,9 @@ public interface OptionConstants { /** A file path to a user's preferred browser. */ public static final FileOption BROWSER_FILE = new FileOption("browser.file", FileOps.NULL_FILE); + /** A file path to a user's preferred browser. */ + public static final StringOption UUID = new StringOption("uuid.string",""); + /** A String used to launch a user's preferred browser. It is tokenized and appended to the file path. */ public static final StringOption BROWSER_STRING = new StringOption("browser.string", ""); From 09b837aa6263fc34082dc34c10ab430c3420d452 Mon Sep 17 00:00:00 2001 From: y4zhang Date: Wed, 12 Jul 2017 14:05:54 -0500 Subject: [PATCH 2/8] create DataCollector file and add openDrJava --- drjava/src/edu/rice/cs/drjava/DrJava.java | 42 ++++++++++- .../rice/cs/drjava/collect/DataCollector.java | 73 +++++++++++++++++++ 2 files changed, 111 insertions(+), 4 deletions(-) create mode 100644 drjava/src/edu/rice/cs/drjava/collect/DataCollector.java diff --git a/drjava/src/edu/rice/cs/drjava/DrJava.java b/drjava/src/edu/rice/cs/drjava/DrJava.java index f1f37315a..a9e14cc19 100644 --- a/drjava/src/edu/rice/cs/drjava/DrJava.java +++ b/drjava/src/edu/rice/cs/drjava/DrJava.java @@ -57,6 +57,7 @@ import edu.rice.cs.util.Log; import edu.rice.cs.util.UnexpectedException; import edu.rice.cs.drjava.model.DrJavaFileUtils; +import edu.rice.cs.drjava.collect.*; /** Startup class for DrJava consisting entirely of static members. The main method reads the .drjava file (creating * one if none exists) to get the critical information required to start the main JVM for DrJava: @@ -242,12 +243,16 @@ public static void main(final String[] args) { if (handleCommandLineArgs(args)) { // Platform-specific UI setup. PlatformFactory.ONLY.beforeUISetup(); - + System.out.println(getOperatingSystem()); + System.out.println(getJavaVersion()); + System.out.println(getInterfaceLanguage()); + DataCollector.drjavaOpened(getOperatingSystem(),getJavaVersion(),getInterfaceLanguage()); // Utilities.showDebug("Calling configureAndLoadDrJavaRoot with args = " + args); configureAndLoadDrJavaRoot(args); } } + public static void configureAndLoadDrJavaRoot(String[] args) { try { System.out.println("r"); @@ -375,8 +380,8 @@ public static void configureAndLoadDrJavaRoot(String[] args) { } else { -System.out.println("yy!"); -//System.out.println(DrJava.getConfig().getSetting(OptionConstants.UUID)); + System.out.println("yy!"); + System.out.println(DrJava.getConfig().getSetting(OptionConstants.UUID)); // No restart -- just invoke DrJavaRoot.main. DrJavaRoot.main(classArgs.toArray(new String[0])); // when we return from here, DrJavaRoot._mainFrame has been initialized @@ -602,7 +607,36 @@ public static void cleanUp() { _jvmArgs.clear(); // Do not set _config or _propertiesFile to null because THEY ARE static } +/** + * Get operating system from system + * @return operating system + */ + private static String getOperatingSystem(){ + return System.getProperty("os.name") + + "/" + System.getProperty("os.arch") + + "/" + System.getProperty("os.version"); + +} + /** + * Get Java version of drjava + * + * @return Java version + */ + + private static String getJavaVersion(){ + + return System.getProperty("java.version"); + } + + /** + * Get language the user use for drjava interface + */ + private static String getInterfaceLanguage(){ + + return "english"; + } + /** Warn if this system is Linux with Compiz. * @return true if is Linux with Compiz; false otherwise */ @@ -677,4 +711,4 @@ public static boolean warnIfLinuxWithCompiz() { return false; // do not warn } } -} +} \ No newline at end of file diff --git a/drjava/src/edu/rice/cs/drjava/collect/DataCollector.java b/drjava/src/edu/rice/cs/drjava/collect/DataCollector.java new file mode 100644 index 000000000..dd0a00bd1 --- /dev/null +++ b/drjava/src/edu/rice/cs/drjava/collect/DataCollector.java @@ -0,0 +1,73 @@ +package edu.rice.cs.drjava.collect; + + +import edu.rice.cs.drjava.DrJava; +import edu.rice.cs.drjava.config.OptionConstants; +import java.util.UUID; +/** + * DataCollector for collecting data from users of DrJava and sending off data to WhiteBox and BlackBox of BlueJ. + * + * This class mainly acts as a proxy for the DataCollectorImpl class, which implements the actual + * collection logic. + */ +public class DataCollector{ + /** + * These three variables can change during the execution: + */ + + private static String uuid; + +// @onThread(value=Tag.Any, requireSynchronized = true) + private static boolean recordingThisSession; + + /** + * Session identifier. Never changes after startSession() has been called: + */ +// @OnThread(value = Tag.Any, requireSynchronized = true) + private static String sessionUUID; + + /** + * Checks whether we should send data. This takes into account whether we + * are in Greenfoot, and opt-in status. It doesn't check whether we have stopped + * sending due to connection problems -- DataSubmitter keeps track of that. + */ + // @OnThread(Tag.Any) + private static synchronized boolean dontSend() + { + return (!recordingThisSession); + } + + public static void drjavaOpened(String os, String javaVersion, String interfaceLanguage){ + startSession(); + System.out.println(DrJava.getConfig().getSetting(OptionConstants.UUID)); + if(dontSend()) return; + //DataCollectorImpl.drjavaOpened(os,javaVersion,interfaceLanguage); + } + + public static synchronized void startSession(){ + uuid = DrJava.getConfig().getSetting(OptionConstants.UUID); + if(!uuidValid()){ + generateUUID(); + } + recordingThisSession = false; + if(recordingThisSession){ + sessionUUID = UUID.randomUUID().toString(); + + } + + } + private static synchronized boolean uuidValid(){ + return (uuid!=null) && (uuid.length()>=32); + + } + + public static synchronized void generateUUID(){ + if(!uuidValid()){ + uuid = UUID.randomUUID().toString(); + } + DrJava.getConfig().setSetting(OptionConstants.UUID, uuid); + + } + + +} From 93f9c9b57ad12a1bcbee01d7d699ecf232fcd1fe Mon Sep 17 00:00:00 2001 From: y4zhang Date: Wed, 12 Jul 2017 14:11:11 -0500 Subject: [PATCH 3/8] connect datacollector to datasubmit --- .../cs/drjava/collect/CollectUtility.java | 48 +++++++++++++++++++ .../cs/drjava/collect/DataCollectorImpl.java | 14 ++++++ .../rice/cs/drjava/collect/DataSubmitter.java | 9 ++++ 3 files changed, 71 insertions(+) create mode 100644 drjava/src/edu/rice/cs/drjava/collect/CollectUtility.java create mode 100644 drjava/src/edu/rice/cs/drjava/collect/DataCollectorImpl.java create mode 100644 drjava/src/edu/rice/cs/drjava/collect/DataSubmitter.java diff --git a/drjava/src/edu/rice/cs/drjava/collect/CollectUtility.java b/drjava/src/edu/rice/cs/drjava/collect/CollectUtility.java new file mode 100644 index 000000000..5f141a917 --- /dev/null +++ b/drjava/src/edu/rice/cs/drjava/collect/CollectUtility.java @@ -0,0 +1,48 @@ +package edu.rice.cs.drjava.collect; + +import org.apache.http.entity.mime.content.StringBody; +import java.nio.charset.Charset; + +class CollectUtility{ + /** + * Cached UTF-8 charset: + */ + private static final Charset utf8 = Charset.forName("UTF-8"); + + /** + * Converts the given String to a StringBody. Null strings are sent the same as empty strings. + */ + static StringBody toBody(String s){ + try { + return new StringBody(s == null ? "" : s, utf8); + } + catch (UnsupportedEncodingException e) { + // Shouldn't happen, because UTF-8 is required to be supported + return null; + } + } + + /** + * Converts the integer to a StringBody + */ + static StringBody toBody(int i) + { + return toBody(Integer.toString(i)); + } + + /** + * Converts the long to a StringBody + */ + static StringBody toBody(long l) + { + return toBody(Long.toString(l)); + } + + /** + * Converts the boolean to a StringBody + */ + static StringBody toBody(boolean b) + { + return toBody(Boolean.toString(b)); + } +} diff --git a/drjava/src/edu/rice/cs/drjava/collect/DataCollectorImpl.java b/drjava/src/edu/rice/cs/drjava/collect/DataCollectorImpl.java new file mode 100644 index 000000000..e88ba05c3 --- /dev/null +++ b/drjava/src/edu/rice/cs/drjava/collect/DataCollectorImpl.java @@ -0,0 +1,14 @@ +package edu.rice.cs.drjava.collect; + +import org.apache.http.entity.mime.MultipartEntity; +public class DataCollectorImpl{ + public static void drjavaOpened(String os, Sring javaVersion, String interfaceLanguage){ + DataSubmitter.initSequence(); + MultipartEntity mpe = new MultipartEntity(); + mpe.addPart("installation[operating_system]",CollectUtility.toBody(os)); + mpe.addPart("installation[java_version]",CollectUtility.toBody(javaVersion)); + mpe.addPart("installation[interface_language]",CollectUtility.toBody(interfaceLanguage)); + + //submitEvent(); + } +} diff --git a/drjava/src/edu/rice/cs/drjava/collect/DataSubmitter.java b/drjava/src/edu/rice/cs/drjava/collect/DataSubmitter.java new file mode 100644 index 000000000..6aa546098 --- /dev/null +++ b/drjava/src/edu/rice/cs/drjava/collect/DataSubmitter.java @@ -0,0 +1,9 @@ +package edu.rice.cs.drjava.collect; + +class DataSubmitter{ + private static int sequenceNum; + + public static void initSequence(){ + sequenceNum =1; + } +} From a438f8a513db1a3b4ec116eeb08b06608501be1c Mon Sep 17 00:00:00 2001 From: y4zhang Date: Tue, 25 Jul 2017 15:54:06 -0500 Subject: [PATCH 4/8] connect new action and reorganize open connections --- drjava/src/edu/rice/cs/drjava/DrJava.java | 6 +++--- .../src/edu/rice/cs/drjava/model/AbstractGlobalModel.java | 4 ++++ drjava/src/edu/rice/cs/drjava/ui/MainFrame.java | 1 - 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/drjava/src/edu/rice/cs/drjava/DrJava.java b/drjava/src/edu/rice/cs/drjava/DrJava.java index a9e14cc19..e19ff7bac 100644 --- a/drjava/src/edu/rice/cs/drjava/DrJava.java +++ b/drjava/src/edu/rice/cs/drjava/DrJava.java @@ -57,7 +57,7 @@ import edu.rice.cs.util.Log; import edu.rice.cs.util.UnexpectedException; import edu.rice.cs.drjava.model.DrJavaFileUtils; -import edu.rice.cs.drjava.collect.*; +//import edu.rice.cs.drjava.collect.*; /** Startup class for DrJava consisting entirely of static members. The main method reads the .drjava file (creating * one if none exists) to get the critical information required to start the main JVM for DrJava: @@ -246,7 +246,7 @@ public static void main(final String[] args) { System.out.println(getOperatingSystem()); System.out.println(getJavaVersion()); System.out.println(getInterfaceLanguage()); - DataCollector.drjavaOpened(getOperatingSystem(),getJavaVersion(),getInterfaceLanguage()); +// DataCollector.drjavaOpened(getOperatingSystem(),getJavaVersion(),getInterfaceLanguage()); // Utilities.showDebug("Calling configureAndLoadDrJavaRoot with args = " + args); configureAndLoadDrJavaRoot(args); } @@ -711,4 +711,4 @@ public static boolean warnIfLinuxWithCompiz() { return false; // do not warn } } -} \ No newline at end of file +} diff --git a/drjava/src/edu/rice/cs/drjava/model/AbstractGlobalModel.java b/drjava/src/edu/rice/cs/drjava/model/AbstractGlobalModel.java index 4d616f812..3522ea488 100644 --- a/drjava/src/edu/rice/cs/drjava/model/AbstractGlobalModel.java +++ b/drjava/src/edu/rice/cs/drjava/model/AbstractGlobalModel.java @@ -158,6 +158,8 @@ import static edu.rice.cs.plt.debug.DebugUtil.debug; +//import edu.rice.cs.drjava.collect.*; + /** In simple terms, a DefaultGlobalModel without an interpreter, compiler, junit testing, debugger or javadoc. * Hence, it only has only document handling functionality * @version $Id$ @@ -1231,6 +1233,7 @@ public OpenDefinitionsDocument newFile(String text) { if (dir == null) dir = getMasterWorkingDirectory(); OpenDefinitionsDocument doc = newFile(dir, text); setActiveDocument(doc); + //DataCollector.newFile(dir, doc); return doc; } @@ -1430,6 +1433,7 @@ private OpenDefinitionsDocument[] _openFiles(File[] files) for(OpenDefinitionsDocument d : alreadyOpenDocuments) { _notifier.handleAlreadyOpenDocument(d); _notifier.fileOpened(d); + //DataCollector.openClass(d) } } diff --git a/drjava/src/edu/rice/cs/drjava/ui/MainFrame.java b/drjava/src/edu/rice/cs/drjava/ui/MainFrame.java index 66c324fb1..88b2a64e1 100644 --- a/drjava/src/edu/rice/cs/drjava/ui/MainFrame.java +++ b/drjava/src/edu/rice/cs/drjava/ui/MainFrame.java @@ -9356,7 +9356,6 @@ public void undoableEditHappened() { public void activeDocumentRefreshed(final OpenDefinitionsDocument active) { assert EventQueue.isDispatchThread(); -// System.err.println("activeDocumentRefreshed"); _recentDocFrame.pokeDocument(active); _refreshDefScrollPane(); From a1b9e62a9f7f4e6956a8b1c448b4121964c45871 Mon Sep 17 00:00:00 2001 From: y4zhang Date: Tue, 25 Jul 2017 15:56:31 -0500 Subject: [PATCH 5/8] remove collector folder so far for compiling --- .../cs/drjava/collect/CollectUtility.java | 48 ------------ .../rice/cs/drjava/collect/DataCollector.java | 73 ------------------- .../cs/drjava/collect/DataCollectorImpl.java | 14 ---- .../rice/cs/drjava/collect/DataSubmitter.java | 9 --- 4 files changed, 144 deletions(-) delete mode 100644 drjava/src/edu/rice/cs/drjava/collect/CollectUtility.java delete mode 100644 drjava/src/edu/rice/cs/drjava/collect/DataCollector.java delete mode 100644 drjava/src/edu/rice/cs/drjava/collect/DataCollectorImpl.java delete mode 100644 drjava/src/edu/rice/cs/drjava/collect/DataSubmitter.java diff --git a/drjava/src/edu/rice/cs/drjava/collect/CollectUtility.java b/drjava/src/edu/rice/cs/drjava/collect/CollectUtility.java deleted file mode 100644 index 5f141a917..000000000 --- a/drjava/src/edu/rice/cs/drjava/collect/CollectUtility.java +++ /dev/null @@ -1,48 +0,0 @@ -package edu.rice.cs.drjava.collect; - -import org.apache.http.entity.mime.content.StringBody; -import java.nio.charset.Charset; - -class CollectUtility{ - /** - * Cached UTF-8 charset: - */ - private static final Charset utf8 = Charset.forName("UTF-8"); - - /** - * Converts the given String to a StringBody. Null strings are sent the same as empty strings. - */ - static StringBody toBody(String s){ - try { - return new StringBody(s == null ? "" : s, utf8); - } - catch (UnsupportedEncodingException e) { - // Shouldn't happen, because UTF-8 is required to be supported - return null; - } - } - - /** - * Converts the integer to a StringBody - */ - static StringBody toBody(int i) - { - return toBody(Integer.toString(i)); - } - - /** - * Converts the long to a StringBody - */ - static StringBody toBody(long l) - { - return toBody(Long.toString(l)); - } - - /** - * Converts the boolean to a StringBody - */ - static StringBody toBody(boolean b) - { - return toBody(Boolean.toString(b)); - } -} diff --git a/drjava/src/edu/rice/cs/drjava/collect/DataCollector.java b/drjava/src/edu/rice/cs/drjava/collect/DataCollector.java deleted file mode 100644 index dd0a00bd1..000000000 --- a/drjava/src/edu/rice/cs/drjava/collect/DataCollector.java +++ /dev/null @@ -1,73 +0,0 @@ -package edu.rice.cs.drjava.collect; - - -import edu.rice.cs.drjava.DrJava; -import edu.rice.cs.drjava.config.OptionConstants; -import java.util.UUID; -/** - * DataCollector for collecting data from users of DrJava and sending off data to WhiteBox and BlackBox of BlueJ. - * - * This class mainly acts as a proxy for the DataCollectorImpl class, which implements the actual - * collection logic. - */ -public class DataCollector{ - /** - * These three variables can change during the execution: - */ - - private static String uuid; - -// @onThread(value=Tag.Any, requireSynchronized = true) - private static boolean recordingThisSession; - - /** - * Session identifier. Never changes after startSession() has been called: - */ -// @OnThread(value = Tag.Any, requireSynchronized = true) - private static String sessionUUID; - - /** - * Checks whether we should send data. This takes into account whether we - * are in Greenfoot, and opt-in status. It doesn't check whether we have stopped - * sending due to connection problems -- DataSubmitter keeps track of that. - */ - // @OnThread(Tag.Any) - private static synchronized boolean dontSend() - { - return (!recordingThisSession); - } - - public static void drjavaOpened(String os, String javaVersion, String interfaceLanguage){ - startSession(); - System.out.println(DrJava.getConfig().getSetting(OptionConstants.UUID)); - if(dontSend()) return; - //DataCollectorImpl.drjavaOpened(os,javaVersion,interfaceLanguage); - } - - public static synchronized void startSession(){ - uuid = DrJava.getConfig().getSetting(OptionConstants.UUID); - if(!uuidValid()){ - generateUUID(); - } - recordingThisSession = false; - if(recordingThisSession){ - sessionUUID = UUID.randomUUID().toString(); - - } - - } - private static synchronized boolean uuidValid(){ - return (uuid!=null) && (uuid.length()>=32); - - } - - public static synchronized void generateUUID(){ - if(!uuidValid()){ - uuid = UUID.randomUUID().toString(); - } - DrJava.getConfig().setSetting(OptionConstants.UUID, uuid); - - } - - -} diff --git a/drjava/src/edu/rice/cs/drjava/collect/DataCollectorImpl.java b/drjava/src/edu/rice/cs/drjava/collect/DataCollectorImpl.java deleted file mode 100644 index e88ba05c3..000000000 --- a/drjava/src/edu/rice/cs/drjava/collect/DataCollectorImpl.java +++ /dev/null @@ -1,14 +0,0 @@ -package edu.rice.cs.drjava.collect; - -import org.apache.http.entity.mime.MultipartEntity; -public class DataCollectorImpl{ - public static void drjavaOpened(String os, Sring javaVersion, String interfaceLanguage){ - DataSubmitter.initSequence(); - MultipartEntity mpe = new MultipartEntity(); - mpe.addPart("installation[operating_system]",CollectUtility.toBody(os)); - mpe.addPart("installation[java_version]",CollectUtility.toBody(javaVersion)); - mpe.addPart("installation[interface_language]",CollectUtility.toBody(interfaceLanguage)); - - //submitEvent(); - } -} diff --git a/drjava/src/edu/rice/cs/drjava/collect/DataSubmitter.java b/drjava/src/edu/rice/cs/drjava/collect/DataSubmitter.java deleted file mode 100644 index 6aa546098..000000000 --- a/drjava/src/edu/rice/cs/drjava/collect/DataSubmitter.java +++ /dev/null @@ -1,9 +0,0 @@ -package edu.rice.cs.drjava.collect; - -class DataSubmitter{ - private static int sequenceNum; - - public static void initSequence(){ - sequenceNum =1; - } -} From 07649676babbac8128b3c5c74447f6f1afe9e42e Mon Sep 17 00:00:00 2001 From: y4zhang Date: Wed, 26 Jul 2017 17:30:43 -0500 Subject: [PATCH 6/8] rename/close/closeAll but save --- drjava/src/edu/rice/cs/drjava/model/AbstractGlobalModel.java | 5 +++-- drjava/src/edu/rice/cs/drjava/ui/MainFrame.java | 5 +++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/drjava/src/edu/rice/cs/drjava/model/AbstractGlobalModel.java b/drjava/src/edu/rice/cs/drjava/model/AbstractGlobalModel.java index 3522ea488..ca0f8833c 100644 --- a/drjava/src/edu/rice/cs/drjava/model/AbstractGlobalModel.java +++ b/drjava/src/edu/rice/cs/drjava/model/AbstractGlobalModel.java @@ -1433,7 +1433,7 @@ private OpenDefinitionsDocument[] _openFiles(File[] files) for(OpenDefinitionsDocument d : alreadyOpenDocuments) { _notifier.handleAlreadyOpenDocument(d); _notifier.fileOpened(d); - //DataCollector.openClass(d) + //DataCollector.openClass(d.getParentDirectory(),d) } } @@ -2092,7 +2092,8 @@ public boolean closeFiles(List docs) { _ensureNotActive(docs); // Close the files in docs. - for (OpenDefinitionsDocument doc : docs) { closeFileWithoutPrompt(doc); } + for (OpenDefinitionsDocument doc : docs) { closeFileWithoutPrompt(doc); } + //for (OpenDefinitionsDocument doc : docs) { DataCollector.closeFile(doc);} return true; } diff --git a/drjava/src/edu/rice/cs/drjava/ui/MainFrame.java b/drjava/src/edu/rice/cs/drjava/ui/MainFrame.java index 88b2a64e1..41932babb 100644 --- a/drjava/src/edu/rice/cs/drjava/ui/MainFrame.java +++ b/drjava/src/edu/rice/cs/drjava/ui/MainFrame.java @@ -5148,6 +5148,7 @@ private void _close() { // Either this is an external file or user actually wants to close it for(OpenDefinitionsDocument doc: l) { _model.closeFile(doc); + //DataCollector.closeFile(doc); } } @@ -5315,9 +5316,13 @@ private boolean _rename() { boolean toReturn = _model.getActiveDocument().saveFileAs(_saveAsSelector); /** Delete the old file if save was successful. */ // TODO: what if delete() fails? (mgricken) + + //File oldFile = fileToDelete; if (toReturn && ! _model.getActiveDocument().getFile().equals(fileToDelete)) fileToDelete.delete(); /** this highlights the document in the navigator */ _model.refreshActiveDocument(); + //File newFile = _model.getActiveDocument().getFile(); + //DataCollector.RenamedClass(oldFile, newFile); return toReturn; } } From ab485c72391082e4876ad05336ca39152ea45a5b Mon Sep 17 00:00:00 2001 From: y4zhang Date: Wed, 9 Aug 2017 17:56:58 -0500 Subject: [PATCH 7/8] finish collecting all related data for compiling event --- .../src/edu/rice/cs/drjava/model/AbstractGlobalModel.java | 6 +++--- .../rice/cs/drjava/model/compiler/DefaultCompilerModel.java | 5 +++++ drjava/src/edu/rice/cs/drjava/ui/MainFrame.java | 3 +-- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/drjava/src/edu/rice/cs/drjava/model/AbstractGlobalModel.java b/drjava/src/edu/rice/cs/drjava/model/AbstractGlobalModel.java index ca0f8833c..229f19f56 100644 --- a/drjava/src/edu/rice/cs/drjava/model/AbstractGlobalModel.java +++ b/drjava/src/edu/rice/cs/drjava/model/AbstractGlobalModel.java @@ -1233,7 +1233,6 @@ public OpenDefinitionsDocument newFile(String text) { if (dir == null) dir = getMasterWorkingDirectory(); OpenDefinitionsDocument doc = newFile(dir, text); setActiveDocument(doc); - //DataCollector.newFile(dir, doc); return doc; } @@ -1435,8 +1434,7 @@ private OpenDefinitionsDocument[] _openFiles(File[] files) _notifier.fileOpened(d); //DataCollector.openClass(d.getParentDirectory(),d) } - } - + } return retDocs.toArray(new OpenDefinitionsDocument[0]); } @@ -3338,6 +3336,8 @@ public void saveTo(OutputStream os) throws IOException { // We don't save if this happens. return false; } + //DefinitionsDocument ddoc = getDocument(); + //DataCollector.newFile(_packageName,_parentDir, ddoc); } /** This method tells the document to prepare all the DrJavaBook and PagePrinter objects. */ diff --git a/drjava/src/edu/rice/cs/drjava/model/compiler/DefaultCompilerModel.java b/drjava/src/edu/rice/cs/drjava/model/compiler/DefaultCompilerModel.java index aad8fbe88..2718e84cd 100644 --- a/drjava/src/edu/rice/cs/drjava/model/compiler/DefaultCompilerModel.java +++ b/drjava/src/edu/rice/cs/drjava/model/compiler/DefaultCompilerModel.java @@ -65,6 +65,8 @@ import edu.rice.cs.plt.io.IOUtil; import edu.rice.cs.plt.iter.IterUtil; import edu.rice.cs.plt.collect.CollectUtil; + +//import edu.rice.cs.drjava.collect.*; // import edu.rice.cs.plt.tuple.Pair; // TODO: use the preceding pair class instead of javalanglevels.Pair; must change javalanglevels code as well @@ -273,6 +275,7 @@ private void _doCompile(List docs) throws IOException { } catch (Throwable t) { DJError err = new DJError(t.toString(), false); + //DataCollector.compiled(filesToCompile, Arrays.asList(err),false,false); _distributeErrors(Arrays.asList(err)); throw new UnexpectedException(t); } @@ -361,11 +364,13 @@ private void _compileFiles(List files, File buildDir) throws IOException { synchronized(_compilerLock) { if (preprocessedFiles == null) { errors.addAll(compiler.compile(files, classPath, null, buildDir, bootClassPath, null, true)); + //DataCollector.compiled(files, errors,true,true); } else { /** If compiling a language level file, do not show warnings, as these are not caught by the language level * parser */ errors.addAll(compiler.compile(preprocessedFiles, classPath, null, buildDir, bootClassPath, null, false)); + //DataCollector.compiled(files, errors,false,true); } } } diff --git a/drjava/src/edu/rice/cs/drjava/ui/MainFrame.java b/drjava/src/edu/rice/cs/drjava/ui/MainFrame.java index 41932babb..1950ccf41 100644 --- a/drjava/src/edu/rice/cs/drjava/ui/MainFrame.java +++ b/drjava/src/edu/rice/cs/drjava/ui/MainFrame.java @@ -5148,7 +5148,6 @@ private void _close() { // Either this is an external file or user actually wants to close it for(OpenDefinitionsDocument doc: l) { _model.closeFile(doc); - //DataCollector.closeFile(doc); } } @@ -5322,7 +5321,7 @@ private boolean _rename() { /** this highlights the document in the navigator */ _model.refreshActiveDocument(); //File newFile = _model.getActiveDocument().getFile(); - //DataCollector.RenamedClass(oldFile, newFile); + //DataCollector.renamedClass(oldFile, newFile); return toReturn; } } From 24bb04c97945205a72061925afba31c20b4eb7d4 Mon Sep 17 00:00:00 2001 From: y4zhang Date: Fri, 8 Sep 2017 21:38:22 -0500 Subject: [PATCH 8/8] dataCollector folder --- .../cs/drjava/collect/CollectUtility.java | 104 ++++++++++++ .../rice/cs/drjava/collect/DataCollector.java | 153 ++++++++++++++++++ .../cs/drjava/collect/DataCollectorImpl.java | 153 ++++++++++++++++++ .../rice/cs/drjava/collect/DataSubmitter.java | 90 +++++++++++ .../edu/rice/cs/drjava/collect/EventName.java | 36 +++++ 5 files changed, 536 insertions(+) create mode 100644 drjava/src/edu/rice/cs/drjava/collect/CollectUtility.java create mode 100644 drjava/src/edu/rice/cs/drjava/collect/DataCollector.java create mode 100644 drjava/src/edu/rice/cs/drjava/collect/DataCollectorImpl.java create mode 100644 drjava/src/edu/rice/cs/drjava/collect/DataSubmitter.java create mode 100644 drjava/src/edu/rice/cs/drjava/collect/EventName.java diff --git a/drjava/src/edu/rice/cs/drjava/collect/CollectUtility.java b/drjava/src/edu/rice/cs/drjava/collect/CollectUtility.java new file mode 100644 index 000000000..b26e682fb --- /dev/null +++ b/drjava/src/edu/rice/cs/drjava/collect/CollectUtility.java @@ -0,0 +1,104 @@ +package edu.rice.cs.drjava.collect; + +import org.apache.http.entity.mime.content.StringBody; +import java.nio.charset.Charset; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.io.*; +import org.apache.http.entity.mime.content.StringBody; + +class CollectUtility{ + /** + * Cached UTF-8 charset: + */ + private static final Charset utf8 = Charset.forName("UTF-8"); + + /** + * Converts the given String to a StringBody. Null strings are sent the same as empty strings. + */ + static StringBody toBody(String s){ + try { + return new StringBody(s == null ? "" : s, utf8); + } + catch (UnsupportedEncodingException e) { + // Shouldn't happen, because UTF-8 is required to be supported + return null; + } + } + + /** + * Converts the integer to a StringBody + */ + static StringBody toBody(int i) + { + return toBody(Integer.toString(i)); + } + + /** + * Converts the long to a StringBody + */ + static StringBody toBody(long l) + { + return toBody(Long.toString(l)); + } + + /** + * Converts the boolean to a StringBody + */ + static StringBody toBody(boolean b) + { + return toBody(Boolean.toString(b)); + } + + static String toPath(File dir, File doc){ + return dir.toURI().relativize(doc.toURI()).getPath(); + } + static StringBody toBodyLocal(File parenDir, OpenDefinitionsDocument sourceFile){ + return toBody(toPath(parentDir, sourceFile)); + } + + /** + * Performs an md5 hash of the given string + */ + static String md5Hash(String src){ + byte[] hash; + try{ + hash = MessageDigest.getInstance("MD5").digest(src.getBytes("UTF-8")); + }catch(NoSuchAlgorithmException e){ + return ""; + } catch (UnsupportedEncodingException e) { + return ""; + } + StringBuilder s = new StringBuilder(); + for(byte b : hash){ + s.append(String.format("%02X", b)); + } + return s.toString(); + + } + + static String readFileAndAnonymise(DefinitionsDocument doc){ + try{ + StringBuilder sb = new StringBuilder(); + FileInputStream inputStream = new FileInputStream(f); + InputStreamReader reader = new InputStreamReader(inputStream, "us-ascii"); + char[] buf = new char[4096]; + + int read = reader.read(buf); + while(read!=-1){ + sb.append(buf, 0, read); + read =reader.read(buf); + } + + reader.close(); + inputStream.close(); + return anonymise(sb.toString()); + } + catch (IOException ioe) {return null;} + } + private static String anonymise(String sourceCode){ + StringBuilder result = new StringBuilder(); + + } +} diff --git a/drjava/src/edu/rice/cs/drjava/collect/DataCollector.java b/drjava/src/edu/rice/cs/drjava/collect/DataCollector.java new file mode 100644 index 000000000..436c1d9d9 --- /dev/null +++ b/drjava/src/edu/rice/cs/drjava/collect/DataCollector.java @@ -0,0 +1,153 @@ +package edu.rice.cs.drjava.collect; + + +import edu.rice.cs.drjava.DrJava; +import edu.rice.cs.drjava.config.OptionConstants; +import java.util.UUID; +/** + * DataCollector for collecting data from users of DrJava and sending off data to WhiteBox and BlackBox of BlueJ. + * + * This class mainly acts as a proxy for the DataCollectorImpl class, which implements the actual + * collection logic. + */ +public class DataCollector{ + /** + * These three variables can change during the execution: + */ + private static String uuid; + +// @onThread(value=Tag.Any, requireSynchronized = true) + private static boolean recordingThisSession; + + /** + * Session identifier. Never changes after startSession() has been called: + */ +// @OnThread(value = Tag.Any, requireSynchronized = true) + private static String sessionUUID; + + /** + * Checks whether we should send data. This takes into account whether we + * are in Greenfoot, and opt-in status. It doesn't check whether we have stopped + * sending due to connection problems -- DataSubmitter keeps track of that. + */ + // @OnThread(Tag.Any) + private static synchronized boolean dontSend() + { + return (!recordingThisSession); + } + /** + * Gets the user's UUID + */ + public static synchronized String getUserID(){ + return uuid; + } + + /** + * Get the session identifier. + */ + public static synchronized String getSessionUuid() + { + return sessionUuid; + } + + //getoptinout method is not used in Bluej, therefore delete it so far + + + public static synchronized void changeOptInOut(boolean forceOptIn){ + + } + + /* + * record when drjava opened + * + *@os operating system + *@javaVersion java version of drjava + *@interfaceLanguage drjava UI language + */ + + public static void drjavaOpened(String os, String javaVersion, String interfaceLanguage){ + startSession(); + if(dontSend()) return; + DataCollectorImpl.drjavaOpened(os,javaVersion,interfaceLanguage); + } + + + /* + * Called from drjavaOpened method to record starting session + * + * + */ + public static synchronized void startSession(){ + uuid = DrJava.getConfig().getSetting(OptionConstants.UUID); + + if(!uuidValid()){ + generateUUID(); + } + recordingThisSession = false; + if(recordingThisSession){ + sessionUUID = UUID.randomUUID().toString(); + + } + + } + + /* + * close drjava + */ + public static void drjavaClosed() + { + if (dontSend()) return; + DataCollectorImpl.drjavaClosed(); + } + + /* + * check if uuid valid + * + * + */ + + private static synchronized boolean uuidValid(){ + return (uuid!=null) && (uuid.length()>=32); + + } + + public static synchronized void generateUUID(){ + if(!uuidValid()){ + uuid = UUID.randomUUID().toString(); + } + DrJava.getConfig().setSetting(OptionConstants.UUID, uuid); + + } + + public static void openClass(File parentDir, OpenDefinitionsDocument sourceFile){ + if(dontSend()) return; + DataCollectorImpl.openClass(parentDir, sourceFile); + } + + public static void newFile(String pkgName, File dir, DefinitionsDocument doc){ + if(dontSend()) return; + DataCollectorImpl.newFile(pkgName, dir, doc); + } + + public static void renamedClass(File oldFile, File newFile){ + if(dontSend()) return; + DataCollectorImpl.renamedClass(oldFile, newFile); + } + + public static void closeFile(File parentDir, OpenDefinitionsDocument doc){ + if(dontSend()) return; + DataCollectorImpl.closeFile(doc); + } + + public static void compiled(List files, List errors, boolean shown, boolean successful){ + if(dontSend()) return; + DataCollectorImpl.compiled(files, errors, shown,successful); + } + +/* public static void selectClass(Package pkg, File sourceFile) + { + if (dontSend()) return; + DataCollectorImpl.selectClass(pkg, sourceFile); + } + */ +} diff --git a/drjava/src/edu/rice/cs/drjava/collect/DataCollectorImpl.java b/drjava/src/edu/rice/cs/drjava/collect/DataCollectorImpl.java new file mode 100644 index 000000000..e4e537ac1 --- /dev/null +++ b/drjava/src/edu/rice/cs/drjava/collect/DataCollectorImpl.java @@ -0,0 +1,153 @@ +package edu.rice.cs.drjava.collect; + +import org.apache.http.entity.mime.MultipartEntity; +public class DataCollectorImpl{ + + private static synchronized void submitEvent(final File sourceFile, final EventName eventname, final Event evt){ + final String projectName = "DrJava"; + final String projectPathHash = CollectUtility.md5Hash(sourceFile.getAbsolutePath()); + final String packgeName = "drjava"; + + final String uuidCopy = DataCollector.getUserID(); + + DataSubmitted.submitEvent(new Event() { + @Override + public void success(Map> fileVersions){ + evt.success(fileVersions); + } + + @Override + public MultipartEntity makeData(int sequenceNum, Map> fileVersions){ + MultipartEntity mpe = evt.makeData(sequenceNum, fileVersions); + + if (mpe == null) + return null; + + mpe.addPart("user[uuid]", CollectUtility.toBody(uuidCopy)); + mpe.addPart("session[id]", CollectUtility.toBody(DataCollector.getSessionUuid())); + // mpe.addPart("participant[experiment]", CollectUtility.toBody(experimentCopy)); + // mpe.addPart("participant[participant]", CollectUtility.toBody(participantCopy)); + + if (projectName != null) + { + mpe.addPart("project[name]", CollectUtility.toBody(projectName)); + mpe.addPart("project[path_hash]", CollectUtility.toBody(projectPathHash)); + + if (packageName != null) + { + mpe.addPart("package[name]", CollectUtility.toBody(packageName)); + } + } + + mpe.addPart("event[source_time]", CollectUtility.toBody(DateFormat.getDateTimeInstance().format(new Date()))); + mpe.addPart("event[name]", CollectUtility.toBody(eventName.getName())); + mpe.addPart("event[sequence_id]", CollectUtility.toBody(Integer.toString(sequenceNum))); + + return mpe; + } + }); + } + + public static void drjavaOpened(String os, Sring javaVersion, String interfaceLanguage){ + DataSubmitter.initSequence(); + MultipartEntity mpe = new MultipartEntity(); + mpe.addPart("installation[operating_system]",CollectUtility.toBody(os)); + mpe.addPart("installation[java_version]",CollectUtility.toBody(javaVersion)); + mpe.addPart("installation[interface_language]",CollectUtility.toBody(interfaceLanguage)); + + submitEvent(null, EventName.DRJAVA_START, new PlaintEvent(mpe)); + } + + public static void openClass(File parentDir, OpenDefinitionsDocument sourceFile){ + classEvent(parentDir, sourceFile, EventName.FILE_OPEN); + } + + public static void closeFile(File parentDir, OpenDefinitionsDocument sourceFile){ + classEvent(parentDir, sourceFile, EventName.FILE_CLOSE); + + } + + public static void classEvent(File parentDir, OpenDefinitionsDocument doc, EventName eventname){ + final MultipartEntity mpe = new MultipartEntity(); + mpe.addPart("event[source_file_name]", CollectUtility.toBodyLocal(parentDir, doc)); + File file = sourceFile.getFile(); + submitEvent(file, eventName, new PlaintEvent(mpe)); + } + +/** + * new class + * + */ + + public static void newFile(String pkgName, File dir, DefinitionsDocument doc){ + addCompleteFiles(pkgName, dir, Collections.singletonList(doc), EventName.ADD); + } + +/** + * called from new class + * + */ + + public static void addCompleteFiles(String pkgName, File dir, List docs, EventName eventName){ + final MultipartEntity mpe = new MultipartEntity(); + for(DefinitionsDocument d : docs){ + String relative = CollectUtility.toPath(dir, d.getOpenDefDoc().getFile()); + mpe.addPart("project[source_files][][name]",CollectUtility.toBody(relative)); + + mpe.addPart("project[source_files][][source_type]", CollectUtility.toBody("java")); + // String anonymisedContent = CollectUtility.readFileAndAnonymise(d); + } + submitEvent(eventName,new Event(){ + @Override + public void success() + }); + } +/** + * Rename an existed class + * + */ + public static void renamedClass(File oldFile, File newFile){ + MultipartEntity mpe = new MultipartEntity(); + mpe.addPart("source_histories[][source_history_type]", CollectUtility.toBody("rename")); + mpe.addPart("source_histories[][content]", CollectUtility.toBody) + } + + public static void compiled(List files, List errors, boolean shown, boolean successful){ + MultipartEntity mpe = new MultipartEntity(); + mpe.addPart("event[compile_success]", CollectUtility.toBody(successful)); + mpe.addPart("event[compile_reason]",CollectUtility.toBody("user")); + for(File f : files){ + mpe.addPart("event[compile_input][][source_file_name]",CollectUtility.toBody(CollectUtility.toPath(f.getParentFile(), f))); + } + for(DJError error : errors){ + //show true if it is warning otherwise it is error + mpe.addPart("event[compile_output][][is_error]",CollectUtility.toBody(error.isWaring())); + mpe.addPart("event[compile_output][][shown]", CollectUtility.toBody(shown)); + mpe.addPart("event[compile_output][][message]", CollectUtility.toBody(error.message())); + //can't get in DrJava, always return -2 + mpe.addPart("event[compile_output][][session_sequence]", CollectUtility.toBody("-2")); + + if(error.fileName()!=null){ + //only can get one type of line number in DJError, therefore regard start and end line as the same number + if(error.lineNumber()>=1) + mpe.addPart("event[compile_output][][start_line]", CollectUtility.toBody(error.lineNumber())); + if(error.lineNumber()>=1) + mpe.addPart("event[compile_output][][end_line]", CollectUtility.toBody(error.lineNumber())); + //start and end column getting from DJError + if(error.startColumn()>=1) + mpe.addPart("event[compile_output][][start_column]",CollectUtility.toBody(error.startColumn())); + if(error.endColumn()>=1) + mpe.addPart("event[compile_output][][end_column]", CollectUtility.toBody(error.endColumn())); + //BlueJ also gives xpath for diagnostic but it can be null, therefore ignore it + //relative confused? + String relative = CollectUtility.toPath(f.getParentFile(), new File(error.fileName())); + mpe.addPart("event[compile_output][][source_file_name]", CollectUtility.toBody(relative)); + } + } + + for(File fi : files){ + submitEvent(fi, EventName.COMPILE, new PlaintEvent(mpe)); + } + } + +} diff --git a/drjava/src/edu/rice/cs/drjava/collect/DataSubmitter.java b/drjava/src/edu/rice/cs/drjava/collect/DataSubmitter.java new file mode 100644 index 000000000..d09094b2f --- /dev/null +++ b/drjava/src/edu/rice/cs/drjava/collect/DataSubmitter.java @@ -0,0 +1,90 @@ +package edu.rice.cs.drjava.collect; + +import java.io.*; +import java.util.*; + +import javafx.application.Platform; + +import org.apache.http.Header; +import org.apache.http.HttpResponse; +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.mime.MultipartEntity; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.params.BasicHttpParams; +import org.apache.http.params.HttpConnectionParams; +import org.apache.http.params.HttpParams; +import org.apache.http.util.EntityUtils; + +class DataSubmitter{ + + private static final String submitUrl = "http://blackbox.bluej.org/master_events"; + //For testing: "http://localhost:3000/master_events"; + + + private static AtomicBoolean givenUp = new AtomicBoolean(false); + /** + * isRunning is only touched while synchonized on queue + */ + private static boolean isRunning = false; + + private static List queue = new LinkedList(); + + private static int sequenceNum; + + /** + * The versions of the files as we have last sent them to the server. + * + * Should only be accessed by the postData method, which is running on + * the event-sending thread + */ + private static Map > fileVersions = new HashMap >(); + + static void submitEvent(Event evt){ + if(giveUp.get()) + return; + + synchronized (queue){ + queue.add(evt); + if(! isRunning){ + new Thread(){ + public void run(){ + processQueue(); + } + }.start(); + isRunning = true; + } + } + } + + /** + *Process the queue of items to be posted to the server + * + */ + + private static void processQueue(){ + while(true){ + Event evt; + synchronized(queue){ + if(queue.isEmpty()){ + isRunning = false; + queue.notifyAll(); + return; + } + evt = queue.remove(0); + } + + + } + } + + public static void initSequence(){ + sequenceNum =1; + } + + public static boolean hasGivenUp() + { + return givenUp.get(); + } +} diff --git a/drjava/src/edu/rice/cs/drjava/collect/EventName.java b/drjava/src/edu/rice/cs/drjava/collect/EventName.java new file mode 100644 index 000000000..03ff60605 --- /dev/null +++ b/drjava/src/edu/rice/cs/drjava/collect/EventName.java @@ -0,0 +1,36 @@ +package edu.rice.cs.drjava.collect; + +/** + * package-visible Enum with basic events that we might sent to the server, excluding debugging and testing events + */ + +enum EventName{ + DRJAVA_START("drjava_start"), + DRJAVA_FINISH("drjava_finish"), + + + ADD("file_add"), + DELETE("file_delete"), + RENAME("rename"), + EDIT("edit"), + COMPILE("compile"), + FILE_OPEN("file_open"), + FILE_SELECT("file_select"), + FILE_CLOSE("file_close"), + + SHOWN_ERROR_INDICATOR("shown_error_indicator"), + SHOWN_ERROR_MESSAGE("shown_error_message"); + + + private final String name; + + private EventName(String name) + { + this.name = name; + } + + public String getName() + { + return name; + } +}