diff --git a/README.md b/README.md index 976f84f..ca2c769 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Reset Your IDE Eval Information -1. Download and install plugin from [Download Link](https://plugins.zhile.io/files/ide-eval-resetter-2.2.4-4959c6.zip). +1. Download and install plugin from [Download Link](https://plugins.zhile.io/files/ide-eval-resetter-2.3.0-064755.zip). * Alternative installation method: * Add "Custom Plugin Repository": `https://plugins.zhile.io` manually (`Settings/Preferences` -> `Plugins`) * Search and install plugin: `IDE Eval Reset` @@ -9,5 +9,3 @@ 4. Restart your IDE. 5. Now you have another 30 days eval time :) 6. For more information, visit [here](https://zhile.io/2020/11/18/jetbrains-eval-reset-da33a93d.html). - -### 目前插件不支持新版本的登录试用,已经有更好更方便的方式了,稍后会推出。 \ No newline at end of file diff --git a/build.gradle b/build.gradle index 8b81a7f..20446ed 100644 --- a/build.gradle +++ b/build.gradle @@ -4,7 +4,7 @@ plugins { } group 'io.zhile.research.intellij' -version '2.2.4' +version '2.3.0' sourceCompatibility = 1.7 targetCompatibility = 1.7 @@ -29,6 +29,8 @@ intellij { patchPluginXml { changeNotes = """
+Release v2.3.0
+  1. fix for 2021.2.3
 Release v2.2.4
   1. fix for 2019.2
 Release v2.2.3
diff --git a/src/main/java/io/zhile/research/intellij/ier/common/LicenseFileRecord.java b/src/main/java/io/zhile/research/intellij/ier/common/LicenseFileRecord.java
index 9aae294..e986dfc 100644
--- a/src/main/java/io/zhile/research/intellij/ier/common/LicenseFileRecord.java
+++ b/src/main/java/io/zhile/research/intellij/ier/common/LicenseFileRecord.java
@@ -22,15 +22,19 @@ public class LicenseFileRecord implements EvalRecord {
         }
     }
 
+    public static void touch(File file) throws Exception {
+        try (DataOutputStream dos = new DataOutputStream(new FileOutputStream(file))) {
+            dos.writeLong(~System.currentTimeMillis());
+        }
+    }
+
     @Override
     public void reset() throws Exception {
         if (!FileUtil.delete(file)) {
             throw new Exception("Remove " + type + " failed: " + file.getAbsolutePath());
         }
 
-        try (DataOutputStream dos = new DataOutputStream(new FileOutputStream(file))) {
-            dos.writeLong(~System.currentTimeMillis());
-        }
+        touch(file);
     }
 
     @Override
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 0bcadcd..8caf6f5 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,6 +7,7 @@ import com.intellij.ide.util.PropertiesComponent;
 import com.intellij.ide.util.PropertiesComponentImpl;
 import com.intellij.openapi.application.PathManager;
 import com.intellij.openapi.util.SystemInfo;
+import io.zhile.research.intellij.ier.helper.AppHelper;
 import io.zhile.research.intellij.ier.helper.Constants;
 import io.zhile.research.intellij.ier.helper.NotificationHelper;
 import io.zhile.research.intellij.ier.helper.ReflectionHelper;
@@ -18,6 +19,8 @@ import java.lang.reflect.Method;
 import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
 import java.util.prefs.BackingStoreException;
 import java.util.prefs.Preferences;
 
@@ -29,6 +32,10 @@ public class Resetter {
     private static final String EVAL_KEY = "evlsprt";
     private static final String AUTO_RESET_KEY = Constants.PLUGIN_PREFS_PREFIX + ".auto_reset." + Constants.IDE_NAME_LOWER + "." + Constants.IDE_HASH;
 
+    private static final Method METHOD_GET_PRODUCT_CODE = ReflectionHelper.getMethod(IdeaPluginDescriptor.class, "getProductCode");
+    private static final Method METHOD_GET_RELEASE_VERSION = ReflectionHelper.getMethod(IdeaPluginDescriptor.class, "getReleaseVersion");
+    private static final Set LICENSE_FILES = new TreeSet<>();
+
     public static List getEvalRecords() {
         List list = new ArrayList<>();
 
@@ -113,10 +120,9 @@ public class Resetter {
                 getAllPrefsKeys(Preferences.userRoot().node(DEFAULT_VENDOR + "/" + name + "/" + Constants.IDE_HASH), prefsList);
             }
 
-            Method methodGetProductCode = ReflectionHelper.getMethod(IdeaPluginDescriptor.class, "getProductCode");
-            if (null != methodGetProductCode) {
+            if (null != METHOD_GET_PRODUCT_CODE) {
                 for (IdeaPluginDescriptor descriptor : PluginManager.getPlugins()) {
-                    String productCode = (String) methodGetProductCode.invoke(descriptor);
+                    String productCode = (String) METHOD_GET_PRODUCT_CODE.invoke(descriptor);
                     if (null == productCode || productCode.isEmpty()) {
                         continue;
                     }
@@ -152,6 +158,54 @@ public class Resetter {
         return list;
     }
 
+    public static void touchLicenses() {
+        try {
+            if (null == METHOD_GET_PRODUCT_CODE || null == METHOD_GET_RELEASE_VERSION) {
+                return;
+            }
+
+            File evalDir = getEvalDir();
+            if (!evalDir.exists()) {
+                evalDir.mkdirs();
+            }
+
+            LICENSE_FILES.add(String.format("%s%s.evaluation.key", AppHelper.getProductCode(), AppHelper.getBuildNumber().getBaselineVersion()));
+
+            for (IdeaPluginDescriptor descriptor : PluginManager.getPlugins()) {
+                addPluginLicense(descriptor);
+            }
+
+            for (String fileName : LICENSE_FILES) {
+                File licenseFile = new File(evalDir, fileName);
+                if (licenseFile.exists()) {
+                    continue;
+                }
+
+                LicenseFileRecord.touch(licenseFile);
+            }
+        } catch (Exception e) {
+            NotificationHelper.showError(null, "Touch eval license failed!");
+        }
+    }
+
+    public static void addPluginLicense(IdeaPluginDescriptor descriptor) {
+        if (null == METHOD_GET_PRODUCT_CODE || null == METHOD_GET_RELEASE_VERSION) {
+            return;
+        }
+
+        try {
+            String productCode = (String) METHOD_GET_PRODUCT_CODE.invoke(descriptor);
+            int releaseVersion = (int) METHOD_GET_RELEASE_VERSION.invoke(descriptor);
+            if (null == productCode || productCode.isEmpty() || 0 == releaseVersion) {
+                return;
+            }
+
+            LICENSE_FILES.add(String.format("plg_%s_%s.evaluation.key", productCode, releaseVersion));
+        } catch (Exception e) {
+            NotificationHelper.showError(null, "Add plugin eval license failed!");
+        }
+    }
+
     public static void reset(List records) {
         for (EvalRecord record : records) {
             Resetter.reset(record);
diff --git a/src/main/java/io/zhile/research/intellij/ier/helper/AppHelper.java b/src/main/java/io/zhile/research/intellij/ier/helper/AppHelper.java
index 816ebce..f1ee766 100644
--- a/src/main/java/io/zhile/research/intellij/ier/helper/AppHelper.java
+++ b/src/main/java/io/zhile/research/intellij/ier/helper/AppHelper.java
@@ -1,6 +1,8 @@
 package io.zhile.research.intellij.ier.helper;
 
+import com.intellij.openapi.application.ApplicationInfo;
 import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.util.BuildNumber;
 
 public class AppHelper {
     public static void restart() {
@@ -11,4 +13,18 @@ public class AppHelper {
             }
         });
     }
+
+    public static String getProductCode() {
+        String productCode = Constants.IDE_NAME;
+
+        if ("IDEA".equals(productCode)) {
+            return productCode.toLowerCase();
+        }
+
+        return productCode;
+    }
+
+    public static BuildNumber getBuildNumber() {
+        return ApplicationInfo.getInstance().getBuild();
+    }
 }
diff --git a/src/main/java/io/zhile/research/intellij/ier/helper/ReflectionHelper.java b/src/main/java/io/zhile/research/intellij/ier/helper/ReflectionHelper.java
index 85c3b28..1f608ec 100644
--- a/src/main/java/io/zhile/research/intellij/ier/helper/ReflectionHelper.java
+++ b/src/main/java/io/zhile/research/intellij/ier/helper/ReflectionHelper.java
@@ -10,4 +10,21 @@ public class ReflectionHelper {
             return null;
         }
     }
+
+    public static Method getMethod(String className, String methodName, Class... methodParameterTypes) {
+        Class klass = getClass(className);
+        if (null == klass) {
+            return null;
+        }
+
+        return getMethod(klass, methodName, methodParameterTypes);
+    }
+
+    public static Class getClass(String name) {
+        try {
+            return Class.forName(name);
+        } catch (ClassNotFoundException e) {
+            return null;
+        }
+    }
 }
diff --git a/src/main/java/io/zhile/research/intellij/ier/listener/AppEventListener.java b/src/main/java/io/zhile/research/intellij/ier/listener/AppEventListener.java
index adb13b2..d38c26b 100644
--- a/src/main/java/io/zhile/research/intellij/ier/listener/AppEventListener.java
+++ b/src/main/java/io/zhile/research/intellij/ier/listener/AppEventListener.java
@@ -32,6 +32,7 @@ public class AppEventListener implements AppLifecycleListener {
 
     public void appClosing() {
         BrokenPlugins.fix();
+        Resetter.touchLicenses();
 
         if (!Resetter.isAutoReset()) {
             return;
diff --git a/src/main/java/io/zhile/research/intellij/ier/listener/ListenerConnector.java b/src/main/java/io/zhile/research/intellij/ier/listener/ListenerConnector.java
index e1a7b76..58347aa 100644
--- a/src/main/java/io/zhile/research/intellij/ier/listener/ListenerConnector.java
+++ b/src/main/java/io/zhile/research/intellij/ier/listener/ListenerConnector.java
@@ -10,6 +10,9 @@ import com.intellij.util.messages.MessageBusConnection;
 import io.zhile.research.intellij.ier.helper.BrokenPlugins;
 import io.zhile.research.intellij.ier.helper.CustomProperties;
 import io.zhile.research.intellij.ier.helper.CustomRepository;
+import io.zhile.research.intellij.ier.helper.ReflectionHelper;
+
+import java.lang.reflect.Method;
 
 public class ListenerConnector {
     private static Disposable disposable;
@@ -27,6 +30,8 @@ public class ListenerConnector {
         MessageBusConnection connection = app.getMessageBus().connect(disposable);
         connection.subscribe(AppLifecycleListener.TOPIC, new AppEventListener());
         connection.subscribe(ApplicationActivationListener.TOPIC, new AppActivationListener());
+
+        callPluginInstallListenerMethod("setup");
     }
 
     public static void dispose() {
@@ -34,7 +39,22 @@ public class ListenerConnector {
             return;
         }
 
+        callPluginInstallListenerMethod("remove");
         Disposer.dispose(disposable);
         disposable = null;
     }
+
+    private static void callPluginInstallListenerMethod(String methodName) {    // reflection for old versions
+        String className = ListenerConnector.class.getPackage().getName() + ".PluginListener";
+        Method method = ReflectionHelper.getMethod(className, methodName);
+        if (null == method) {
+            return;
+        }
+
+        try {
+            method.invoke(null);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
 }
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 70fc1aa..4e65c68 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
@@ -2,16 +2,45 @@ package io.zhile.research.intellij.ier.listener;
 
 import com.intellij.ide.plugins.DynamicPluginListener;
 import com.intellij.ide.plugins.IdeaPluginDescriptor;
+import com.intellij.ide.plugins.PluginStateListener;
+import com.intellij.ide.plugins.PluginStateManager;
 import com.intellij.openapi.actionSystem.ActionManager;
 import com.intellij.openapi.actionSystem.AnAction;
 import com.intellij.openapi.actionSystem.DefaultActionGroup;
+import com.intellij.openapi.application.ApplicationManager;
+import io.zhile.research.intellij.ier.common.Resetter;
 import io.zhile.research.intellij.ier.helper.Constants;
 import io.zhile.research.intellij.ier.helper.NotificationHelper;
 import io.zhile.research.intellij.ier.helper.PluginHelper;
 import io.zhile.research.intellij.ier.tw.MainToolWindowFactory;
 import org.jetbrains.annotations.NotNull;
 
-public class PluginListener implements DynamicPluginListener {
+public class PluginListener implements DynamicPluginListener, PluginStateListener {
+    private static final PluginStateListener stateListener = new PluginListener();
+
+    public static void setup() {
+        PluginStateManager.addStateListener(stateListener);
+    }
+
+    public static void remove() {
+        PluginStateManager.removeStateListener(stateListener);
+    }
+
+    @Override
+    public void install(@NotNull final IdeaPluginDescriptor descriptor) {
+        ApplicationManager.getApplication().invokeLater(new Runnable() {
+            @Override
+            public void run() {
+                Resetter.addPluginLicense(descriptor);
+            }
+        });
+    }
+
+    @Override
+    public void uninstall(@NotNull IdeaPluginDescriptor descriptor) {
+
+    }
+
     @Override
     public void pluginLoaded(@NotNull IdeaPluginDescriptor pluginDescriptor) {
         if (!PluginHelper.myself(pluginDescriptor)) {
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 2eb23a0..231e68f 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
@@ -49,6 +49,21 @@ public class MainForm {
         });
     }
 
+    private static void boldFont(Component component) {
+        Font font = component.getFont();
+        component.setFont(font.deriveFont(font.getStyle() | Font.BOLD));
+    }
+
+    private static void addActionEventListener(final AbstractButton button, final ActionListener listener, Disposable disposable) {
+        button.addActionListener(listener);
+        Disposer.register(disposable, new Disposable() {
+            @Override
+            public void dispose() {
+                button.removeActionListener(listener);
+            }
+        });
+    }
+
     public JPanel getContent(Disposable disposable) {
         Disposer.register(disposable, new Disposable() {
             @Override
@@ -117,6 +132,7 @@ public class MainForm {
             return;
         }
 
+        Resetter.touchLicenses();
         Resetter.reset(Resetter.getEvalRecords());
         ResetTimeHelper.resetLastResetTime();
         listModel.clear();
@@ -127,19 +143,4 @@ public class MainForm {
 
         AppHelper.restart();
     }
-
-    private static void boldFont(Component component) {
-        Font font = component.getFont();
-        component.setFont(font.deriveFont(font.getStyle() | Font.BOLD));
-    }
-
-    private static void addActionEventListener(final AbstractButton button, final ActionListener listener, Disposable disposable) {
-        button.addActionListener(listener);
-        Disposer.register(disposable, new Disposable() {
-            @Override
-            public void dispose() {
-                button.removeActionListener(listener);
-            }
-        });
-    }
 }