diff --git a/build.gradle b/build.gradle index e43db1f..eb01083 100644 --- a/build.gradle +++ b/build.gradle @@ -4,7 +4,7 @@ plugins { } group 'io.zhile.research.intellij' -version '2.1.3' +version '2.1.4' sourceCompatibility = 1.8 targetCompatibility = 1.8 @@ -29,6 +29,8 @@ intellij { patchPluginXml { changeNotes """
+Release v2.1.4
+  1. fix reference
 Release v2.1.3
   1. add version in UI
 Release v2.1.2
diff --git a/src/main/java/io/zhile/research/intellij/ier/action/ResetAction.java b/src/main/java/io/zhile/research/intellij/ier/action/ResetAction.java
index 5ee49ed..b1eac47 100644
--- a/src/main/java/io/zhile/research/intellij/ier/action/ResetAction.java
+++ b/src/main/java/io/zhile/research/intellij/ier/action/ResetAction.java
@@ -15,18 +15,20 @@ import com.intellij.openapi.wm.ex.ToolWindowManagerEx;
 import io.zhile.research.intellij.ier.component.ResetTimer;
 import io.zhile.research.intellij.ier.helper.Constants;
 import io.zhile.research.intellij.ier.helper.CustomRepository;
+import io.zhile.research.intellij.ier.helper.PluginHelper;
 import io.zhile.research.intellij.ier.helper.ProjectHelper;
 import io.zhile.research.intellij.ier.tw.MainToolWindowFactory;
 import io.zhile.research.intellij.ier.ui.dialog.MainDialog;
 import org.jetbrains.annotations.NotNull;
 
+import java.lang.ref.WeakReference;
+
 public class ResetAction extends AnAction implements DumbAware {
-    private static final String ACTION_NAME = "Eval Reset";
     private static final DataKey NOTIFICATION_KEY = DataKey.create("Notification");
 
     public ResetAction() {
-        super(ACTION_NAME, "Reset my IDE eval information", AllIcons.General.Reset);
-        new ResetTimer().start(this);
+        super(Constants.ACTION_NAME, "Reset my IDE eval information", AllIcons.General.Reset);
+        ResetTimer.start(new WeakReference<>(this));
 
         CustomRepository.checkAndAdd(CustomRepository.DEFAULT_HOST);
     }
@@ -41,23 +43,23 @@ public class ResetAction extends AnAction implements DumbAware {
         }
 
         if (project == null) {
-            MainDialog mainDialog = new MainDialog(ACTION_NAME);
+            MainDialog mainDialog = new MainDialog(Constants.ACTION_NAME);
             mainDialog.show();
 
             return;
         }
 
-        ToolWindow toolWindow = ToolWindowManager.getInstance(project).getToolWindow(ACTION_NAME);
+        ToolWindow toolWindow = ToolWindowManager.getInstance(project).getToolWindow(Constants.ACTION_NAME);
         if (null == toolWindow) {
             ToolWindowEP ep = new ToolWindowEP();
-            ep.id = ACTION_NAME;
+            ep.id = Constants.ACTION_NAME;
             ep.anchor = ToolWindowAnchor.BOTTOM.toString();
             ep.icon = "AllIcons.General.Reset";
             ep.factoryClass = MainToolWindowFactory.class.getName();
-            ep.setPluginDescriptor(Constants.PLUGIN_DESC);
+            ep.setPluginDescriptor(PluginHelper.getPluginDescriptor());
             ToolWindowManagerEx.getInstanceEx(project).initToolWindow(ep);
 
-            toolWindow = ToolWindowManager.getInstance(project).getToolWindow(ACTION_NAME);
+            toolWindow = ToolWindowManager.getInstance(project).getToolWindow(Constants.ACTION_NAME);
         }
 
         toolWindow.show(null);
diff --git a/src/main/java/io/zhile/research/intellij/ier/common/Resetter.java b/src/main/java/io/zhile/research/intellij/ier/common/Resetter.java
index b60ba52..3c4f3af 100644
--- a/src/main/java/io/zhile/research/intellij/ier/common/Resetter.java
+++ b/src/main/java/io/zhile/research/intellij/ier/common/Resetter.java
@@ -7,7 +7,7 @@ import com.intellij.openapi.application.PathManager;
 import com.intellij.openapi.util.SystemInfo;
 import io.zhile.research.intellij.ier.helper.Constants;
 import io.zhile.research.intellij.ier.helper.NotificationHelper;
-import io.zhile.research.intellij.ier.helper.Reflection;
+import io.zhile.research.intellij.ier.helper.ReflectionHelper;
 import org.jdom.Element;
 
 import java.io.File;
@@ -67,7 +67,7 @@ public class Resetter {
             List prefsList = new ArrayList<>();
             getAllPrefsKeys(Preferences.userRoot().node(IDE_EVAL_PREFIX), prefsList);
 
-            Method methodGetProductCode = Reflection.getMethod(IdeaPluginDescriptor.class, "getProductCode");
+            Method methodGetProductCode = ReflectionHelper.getMethod(IdeaPluginDescriptor.class, "getProductCode");
             if (null != methodGetProductCode) {
                 for (IdeaPluginDescriptor descriptor : PluginManager.getPlugins()) {
                     String productCode = (String) methodGetProductCode.invoke(descriptor);
diff --git a/src/main/java/io/zhile/research/intellij/ier/component/ResetTimer.java b/src/main/java/io/zhile/research/intellij/ier/component/ResetTimer.java
index 230e01b..26d8288 100644
--- a/src/main/java/io/zhile/research/intellij/ier/component/ResetTimer.java
+++ b/src/main/java/io/zhile/research/intellij/ier/component/ResetTimer.java
@@ -6,23 +6,22 @@ import com.intellij.notification.Notification;
 import com.intellij.notification.NotificationType;
 import com.intellij.openapi.actionSystem.AnAction;
 import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.project.ProjectManager;
+import com.intellij.util.concurrency.AppExecutorUtil;
 import io.zhile.research.intellij.ier.action.RestartAction;
 import io.zhile.research.intellij.ier.common.Resetter;
-import io.zhile.research.intellij.ier.helper.Constants;
-import io.zhile.research.intellij.ier.helper.DateTime;
-import io.zhile.research.intellij.ier.helper.NotificationHelper;
+import io.zhile.research.intellij.ier.helper.*;
 import io.zhile.research.intellij.ier.listener.AppEventListener;
 
-import java.util.Arrays;
-import java.util.Timer;
-import java.util.TimerTask;
+import java.lang.ref.WeakReference;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
 
 public class ResetTimer {
     private static final long RESET_PERIOD = 2160000000L; // 25 days
     private static final String RESET_KEY = Constants.PLUGIN_PREFS_PREFIX + "." + Constants.IDE_NAME_LOWER + "." + Constants.IDE_HASH;
 
+    private static ScheduledFuture scheduledFuture;
+
     public static long getLastResetTime() {
         return Prefs.getLong(RESET_KEY, 0L);
     }
@@ -38,47 +37,39 @@ public class ResetTimer {
         return lastResetTime > 0 ? DateTime.getStringFromTimestamp(lastResetTime) : "Not yet";
     }
 
-    public void start(final AnAction resetAction) {
-        ApplicationManager.getApplication().getMessageBus().connect().subscribe(AppLifecycleListener.TOPIC, new AppEventListener());
+    public synchronized static void start(final WeakReference weakResetAction) {
+        if (scheduledFuture != null) {
+            return;
+        }
 
-        new Timer().schedule(new TimerTask() {
-            @Override
-            public void run() {
-                new ResetTimerTask(getLastResetTime(), resetAction).run();
+        ApplicationManager.getApplication().getMessageBus().connect().subscribe(AppLifecycleListener.TOPIC, new AppEventListener());
+        scheduledFuture = AppExecutorUtil.getAppScheduledExecutorService().scheduleWithFixedDelay(() -> {
+            if (System.currentTimeMillis() - getLastResetTime() <= RESET_PERIOD) {
+                return;
             }
-        }, 3000);
+
+            stop();
+
+            AnAction resetAction = weakResetAction.get();
+            if (resetAction == null) {
+                return;
+            }
+
+            AnAction action = Resetter.isAutoReset() ? new RestartAction() : resetAction;
+            String message = "It has been a long time since the last reset!\nWould you like to reset it again?";
+            Notification notification = NotificationHelper.NOTIFICATION_GROUP.createNotification(PluginHelper.getPluginName(), null, message, NotificationType.INFORMATION);
+            notification.addAction(action);
+
+            notification.notify(ProjectHelper.getCurrentProject());
+        }, 3, 600, TimeUnit.SECONDS);
     }
 
-    protected static class ResetTimerTask extends TimerTask {
-        private final long lastResetTime;
-        private final AnAction resetAction;
-
-        public ResetTimerTask(long lastResetTime, AnAction resetAction) {
-            this.lastResetTime = lastResetTime;
-            this.resetAction = resetAction;
+    public synchronized static void stop() {
+        if (scheduledFuture == null || scheduledFuture.isCancelled()) {
+            return;
         }
 
-        @Override
-        public void run() {
-            do {
-                if (System.currentTimeMillis() - lastResetTime <= RESET_PERIOD) {
-                    break;
-                }
-
-                AnAction action = Resetter.isAutoReset() ? new RestartAction() : resetAction;
-                String message = "It has been a long time since the last reset!\nWould you like to reset it again?";
-                Notification notification = NotificationHelper.NOTIFICATION_GROUP.createNotification(Constants.PLUGIN_NAME, null, message, NotificationType.INFORMATION);
-                notification.addAction(action);
-
-                Project[] projects = ProjectManager.getInstance().getOpenProjects();
-                if (projects.length == 0) {
-                    notification.notify(null);
-                } else {
-                    Arrays.stream(projects).forEach(notification::notify);
-                }
-            } while (false);
-
-            new Timer().schedule(new ResetTimerTask(lastResetTime, resetAction), 600000); // 10 min
-        }
+        scheduledFuture.cancel(false);
+        scheduledFuture = null;
     }
 }
diff --git a/src/main/java/io/zhile/research/intellij/ier/helper/Constants.java b/src/main/java/io/zhile/research/intellij/ier/helper/Constants.java
index d1e4f98..31f2358 100644
--- a/src/main/java/io/zhile/research/intellij/ier/helper/Constants.java
+++ b/src/main/java/io/zhile/research/intellij/ier/helper/Constants.java
@@ -1,19 +1,12 @@
 package io.zhile.research.intellij.ier.helper;
 
-import com.intellij.ide.plugins.IdeaPluginDescriptor;
-import com.intellij.ide.plugins.PluginManager;
-import com.intellij.ide.plugins.cl.PluginClassLoader;
 import com.intellij.openapi.application.ApplicationNamesInfo;
 import com.intellij.openapi.application.PathManager;
-import com.intellij.openapi.extensions.PluginId;
 import com.intellij.openapi.util.io.FileUtil;
 
 public class Constants {
-    public static final PluginClassLoader CLASS_LOADER = (PluginClassLoader) Constants.class.getClassLoader();
-    public static final PluginId PLUGIN_ID = CLASS_LOADER.getPluginId();
-    public static final IdeaPluginDescriptor PLUGIN_DESC = PluginManager.getPlugin(PLUGIN_ID);
-    public static final String PLUGIN_NAME = PLUGIN_DESC.getName();
-    public static final String PLUGIN_VERSION = PLUGIN_DESC.getVersion();
+    public static final String ACTION_NAME = "Eval Reset";
+    public static final String PLUGIN_ID_STR = "io.zhile.research.ide-eval-resetter";
     public static final String IDE_NAME = ApplicationNamesInfo.getInstance().getProductName();
     public static final String IDE_NAME_LOWER = IDE_NAME.toLowerCase();
     public static final String IDE_HASH = Integer.toHexString(FileUtil.pathHashCode(PathManager.getHomePath()));
diff --git a/src/main/java/io/zhile/research/intellij/ier/helper/CustomRepository.java b/src/main/java/io/zhile/research/intellij/ier/helper/CustomRepository.java
index 4025ac7..75c3086 100644
--- a/src/main/java/io/zhile/research/intellij/ier/helper/CustomRepository.java
+++ b/src/main/java/io/zhile/research/intellij/ier/helper/CustomRepository.java
@@ -17,7 +17,7 @@ public class CustomRepository {
 
         hosts.add(host);
 
-        Method method = Reflection.getMethod(UpdateSettings.class, "setThirdPartyPluginsAllowed", boolean.class);
+        Method method = ReflectionHelper.getMethod(UpdateSettings.class, "setThirdPartyPluginsAllowed", boolean.class);
         if (method != null) {
             try {
                 method.invoke(UpdateSettings.getInstance(), true);
diff --git a/src/main/java/io/zhile/research/intellij/ier/helper/NotificationHelper.java b/src/main/java/io/zhile/research/intellij/ier/helper/NotificationHelper.java
index 58df34d..20e30ca 100644
--- a/src/main/java/io/zhile/research/intellij/ier/helper/NotificationHelper.java
+++ b/src/main/java/io/zhile/research/intellij/ier/helper/NotificationHelper.java
@@ -9,11 +9,11 @@ import com.intellij.openapi.project.Project;
 import org.jetbrains.annotations.Nullable;
 
 public class NotificationHelper {
-    public static final NotificationGroup NOTIFICATION_GROUP = new NotificationGroup(Constants.PLUGIN_ID.getIdString(), NotificationDisplayType.BALLOON, true, null, AllIcons.General.Reset);
+    public static final NotificationGroup NOTIFICATION_GROUP = new NotificationGroup(Constants.PLUGIN_ID_STR, NotificationDisplayType.BALLOON, true, null, AllIcons.General.Reset);
 
     public static Notification show(@Nullable Project project, String title, String subtitle, String content, NotificationType type) {
         if (title == null) {
-            title = Constants.PLUGIN_NAME;
+            title = PluginHelper.getPluginName();
         }
 
         Notification notification = NOTIFICATION_GROUP.createNotification(title, subtitle, content, type);
diff --git a/src/main/java/io/zhile/research/intellij/ier/helper/PluginHelper.java b/src/main/java/io/zhile/research/intellij/ier/helper/PluginHelper.java
new file mode 100644
index 0000000..1eccec5
--- /dev/null
+++ b/src/main/java/io/zhile/research/intellij/ier/helper/PluginHelper.java
@@ -0,0 +1,25 @@
+package io.zhile.research.intellij.ier.helper;
+
+import com.intellij.ide.plugins.IdeaPluginDescriptor;
+import com.intellij.ide.plugins.PluginManager;
+import com.intellij.openapi.extensions.PluginId;
+
+public class PluginHelper {
+    private static final IdeaPluginDescriptor PLUGIN_DESCRIPTOR = PluginManager.getPlugin(getPluginId());
+
+    public static PluginId getPluginId() {
+        return PluginId.getId(Constants.PLUGIN_ID_STR);
+    }
+
+    public static IdeaPluginDescriptor getPluginDescriptor() {
+        return PLUGIN_DESCRIPTOR;
+    }
+
+    public static String getPluginName() {
+        return PLUGIN_DESCRIPTOR == null ? "UNKNOWN" : PLUGIN_DESCRIPTOR.getName();
+    }
+
+    public static String getPluginVersion() {
+        return PLUGIN_DESCRIPTOR == null ? "UNKNOWN" : PLUGIN_DESCRIPTOR.getVersion();
+    }
+}
diff --git a/src/main/java/io/zhile/research/intellij/ier/helper/Reflection.java b/src/main/java/io/zhile/research/intellij/ier/helper/ReflectionHelper.java
similarity index 91%
rename from src/main/java/io/zhile/research/intellij/ier/helper/Reflection.java
rename to src/main/java/io/zhile/research/intellij/ier/helper/ReflectionHelper.java
index 6f7465e..85c3b28 100644
--- a/src/main/java/io/zhile/research/intellij/ier/helper/Reflection.java
+++ b/src/main/java/io/zhile/research/intellij/ier/helper/ReflectionHelper.java
@@ -2,7 +2,7 @@ package io.zhile.research.intellij.ier.helper;
 
 import java.lang.reflect.Method;
 
-public class Reflection {
+public class ReflectionHelper {
     public static Method getMethod(Class klass, String methodName, Class... methodParameterTypes) {
         try {
             return klass.getMethod(methodName, methodParameterTypes);
diff --git a/src/main/java/io/zhile/research/intellij/ier/listener/PluginListener.java b/src/main/java/io/zhile/research/intellij/ier/listener/PluginListener.java
index 69e91ed..fd9e7c9 100644
--- a/src/main/java/io/zhile/research/intellij/ier/listener/PluginListener.java
+++ b/src/main/java/io/zhile/research/intellij/ier/listener/PluginListener.java
@@ -3,7 +3,12 @@ package io.zhile.research.intellij.ier.listener;
 import com.intellij.ide.plugins.DynamicPluginListener;
 import com.intellij.ide.plugins.IdeaPluginDescriptor;
 import com.intellij.openapi.actionSystem.ActionManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.wm.ToolWindowManager;
+import io.zhile.research.intellij.ier.component.ResetTimer;
+import io.zhile.research.intellij.ier.helper.Constants;
 import io.zhile.research.intellij.ier.helper.NotificationHelper;
+import io.zhile.research.intellij.ier.helper.ProjectHelper;
 import org.jetbrains.annotations.NotNull;
 
 public class PluginListener implements DynamicPluginListener {
@@ -13,4 +18,16 @@ public class PluginListener implements DynamicPluginListener {
 
         NotificationHelper.showInfo(null, "Plugin installed successfully! Now enjoy it~");
     }
+
+    @Override
+    public void beforePluginUnload(@NotNull IdeaPluginDescriptor pluginDescriptor, boolean isUpdate) {
+        ResetTimer.stop();
+
+        Project project = ProjectHelper.getCurrentProject();
+        if (project == null) {
+            return;
+        }
+
+        ToolWindowManager.getInstance(project).unregisterToolWindow(Constants.ACTION_NAME);
+    }
 }
diff --git a/src/main/java/io/zhile/research/intellij/ier/ui/form/MainForm.java b/src/main/java/io/zhile/research/intellij/ier/ui/form/MainForm.java
index 7b73066..ae286c9 100644
--- a/src/main/java/io/zhile/research/intellij/ier/ui/form/MainForm.java
+++ b/src/main/java/io/zhile/research/intellij/ier/ui/form/MainForm.java
@@ -7,7 +7,7 @@ import com.intellij.openapi.ui.Messages;
 import io.zhile.research.intellij.ier.common.EvalRecord;
 import io.zhile.research.intellij.ier.common.Resetter;
 import io.zhile.research.intellij.ier.component.ResetTimer;
-import io.zhile.research.intellij.ier.helper.Constants;
+import io.zhile.research.intellij.ier.helper.PluginHelper;
 import io.zhile.research.intellij.ier.listener.AppEventListener;
 
 import javax.swing.*;
@@ -38,7 +38,7 @@ public class MainForm {
         boldFont(lblLastResetTimeLabel);
         reloadLastResetTime();
 
-        lblVersion.setText("v" + Constants.PLUGIN_VERSION);
+        lblVersion.setText("v" + PluginHelper.getPluginVersion());
 
         chkResetAuto.setSelected(Resetter.isAutoReset());
         chkResetAuto.addActionListener(new AbstractAction() {
@@ -88,7 +88,7 @@ public class MainForm {
     }
 
     private void resetEvalItems() {
-        if (Messages.YES != Messages.showYesNoDialog("Your IDE will restart after reset!\nAre your sure to reset?", Constants.PLUGIN_NAME, AllIcons.General.Reset)) {
+        if (Messages.YES != Messages.showYesNoDialog("Your IDE will restart after reset!\nAre your sure to reset?", PluginHelper.getPluginName(), AllIcons.General.Reset)) {
             return;
         }