Prechádzať zdrojové kódy

第一轮整体测试,代码优化、逻辑完善、bug修复

JustryDeng 5 rokov pred
rodič
commit
c67bd6713f
32 zmenil súbory, kde vykonal 653 pridanie a 80 odobranie
  1. 1 0
      .gitignore
  2. 7 0
      class-winter-core/pom.xml
  3. 4 1
      class-winter-core/src/main/java/winter/com/ideaaedi/classwinter/Forward.java
  4. 3 3
      class-winter-core/src/main/java/winter/com/ideaaedi/classwinter/Reverses.java
  5. 3 5
      class-winter-core/src/main/java/winter/com/ideaaedi/classwinter/executor/DecryptExecutor.java
  6. 133 30
      class-winter-core/src/main/java/winter/com/ideaaedi/classwinter/executor/EncryptExecutor.java
  7. 1 1
      class-winter-core/src/main/java/winter/com/ideaaedi/classwinter/pakage-info.java
  8. 30 0
      class-winter-core/src/main/java/winter/com/ideaaedi/classwinter/util/Constant.java
  9. 1 0
      class-winter-core/src/main/java/winter/com/ideaaedi/classwinter/util/EncryptUtil.java
  10. 17 11
      class-winter-core/src/main/java/winter/com/ideaaedi/classwinter/util/JarUtil.java
  11. 1 1
      class-winter-core/src/main/java/winter/com/ideaaedi/classwinter/util/JavaagentCmdArgs.java
  12. 16 16
      class-winter-core/src/main/java/winter/com/ideaaedi/classwinter/util/RsaUtil.java
  13. 71 0
      class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/AlreadyProtectedLibs_Test.java
  14. 44 0
      class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/Debug_Test.java
  15. 44 0
      class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/ExcludePrefix_Test.java
  16. 44 0
      class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/FinalName_Test.java
  17. 44 0
      class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/IncludeLibs_Test.java
  18. 44 0
      class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/IncludePrefix_Test.java
  19. 5 5
      class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/MixTest.java
  20. 44 0
      class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/OriginJarOrWar_Test.java
  21. 1 1
      class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/ProtectedLibTest.java
  22. 1 1
      class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/ReversesTest.java
  23. 44 0
      class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/SupportFile_Test.java
  24. 44 0
      class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/Tips_Test.java
  25. BIN
      class-winter-core/src/test/resources/boot-jar.jar
  26. BIN
      class-winter-core/src/test/resources/my-project-with-encrypted-lib-have-pwd.jar
  27. BIN
      class-winter-core/src/test/resources/my-project-with-encrypted-lib-no-pwd.jar
  28. BIN
      class-winter-core/src/test/resources/my-project-with-normal-lib.jar
  29. BIN
      class-winter-core/src/test/resources/normal-jar.jar
  30. BIN
      class-winter-core/src/test/resources/war-project.war
  31. 1 1
      class-winter-maven-plugin/pom.xml
  32. 5 4
      class-winter-maven-plugin/src/main/java/winter/com/ideaaedi/classwinter/plugin/ClassWinterPlugin.java

+ 1 - 0
.gitignore

@@ -1,2 +1,3 @@
 *.iml
 .idea
+target

+ 7 - 0
class-winter-core/pom.xml

@@ -18,6 +18,13 @@
             <artifactId>javassist</artifactId>
             <version>3.27.0-GA</version>
         </dependency>
+
+        <!-- https://mvnrepository.com/artifact/dom4j/dom4j -->
+        <dependency>
+            <groupId>dom4j</groupId>
+            <artifactId>dom4j</artifactId>
+            <version>1.6.1</version>
+        </dependency>
     </dependencies>
 
     <build>

+ 4 - 1
class-winter-core/src/main/java/winter/com/ideaaedi/classwinter/Forward.java

@@ -29,8 +29,9 @@ public class Forward {
         String finalName = parseValueByPrefixFromTail("finalName=", args);
         String includeLibs = parseValueByPrefixFromTail("includeLibs=", args);
         String alreadyProtectedLibs = parseValueByPrefixFromTail("alreadyProtectedLibs=", args);
-        String debug = parseValueByPrefixFromTail("debug=", args);
         String tips = parseValueByPrefixFromTail("tips=", args);
+        String supportFile = parseValueByPrefixFromTail("supportFile=", args);
+        String debug = parseValueByPrefixFromTail("debug=", args);
         
         Logger.ENABLE_DEBUG.set(Boolean.parseBoolean(debug));
         Logger.debug(Forward.class, "You input arg originJarOrWar -> " + originJarOrWar);
@@ -40,6 +41,7 @@ public class Forward {
         Logger.debug(Forward.class, "You input arg includeLibs -> " + includeLibs);
         Logger.debug(Forward.class, "You input arg alreadyProtectedLibs -> " + alreadyProtectedLibs);
         Logger.debug(Forward.class, "You input arg tips -> " + tips);
+        Logger.debug(Forward.class, "You input arg supportFile -> " + supportFile);
         Logger.debug(Forward.class, "You input arg debug -> " + debug);
         
         // 构造加密执行器
@@ -51,6 +53,7 @@ public class Forward {
                 .includeLibs(includeLibs)
                 .alreadyProtectedLibs(alreadyProtectedLibs)
                 .debug(Boolean.parseBoolean(debug))
+                .supportFile(supportFile)
                 .tips(tips)
                 .build();
     

+ 3 - 3
class-winter-core/src/main/java/winter/com/ideaaedi/classwinter/Reverses.java

@@ -92,7 +92,7 @@ public class Reverses {
                                     + (StrUtil.isEmpty(javaagentCmdArgs.getPassword()) ? e.getMessage() : "please ensure your password is correct."));
                             System.exit(-1);
                             // 上一步System.exit(-1)就退出程序了,照理说是不会走到下面这里的(,不过为了以防万一,这里打出提醒, class-winter失效)
-                            for (int i = 0; i < 10; i++) {
+                            for (int i = 0; i < Constant.TEN; i++) {
                                 Logger.error(Reverses.class, "!!!!!!!!!!! class-winter Invalidation. !!!!!!!!!!!");
                             }
                             return null;
@@ -114,7 +114,7 @@ public class Reverses {
                                     + "\t2. Ensure 'Your lib "+ lib +"'s password is correct ?'");
                             System.exit(-1);
                             // 上一步System.exit(-1)就退出程序了,照理说是不会走到下面这里的(,不过为了以防万一,这里打出提醒, class-winter失效)
-                            for (int i = 0; i < 10; i++) {
+                            for (int i = 0; i < Constant.TEN; i++) {
                                 Logger.error(Reverses.class, "!!!!!!!!!!! class-winter Invalidation. !!!!!!!!!!!");
                             }
                             return null;
@@ -135,7 +135,7 @@ public class Reverses {
                  * @return lib名称
                  */
                 private String parseLib(String classWinterInfoDir) {
-                    classWinterInfoDir = classWinterInfoDir.replace(Constant.DEFAULT_ENCRYPTED_CLASSES_SAVE_DIR, "");
+                    classWinterInfoDir = classWinterInfoDir.replace(Constant.MANIFEST_FILE, "");
                     return classWinterInfoDir.replace("_jar/", Constant.JAR_SUFFIX);
                 }
             });

+ 3 - 5
class-winter-core/src/main/java/winter/com/ideaaedi/classwinter/executor/DecryptExecutor.java

@@ -52,7 +52,7 @@ public class DecryptExecutor {
      * @return  解压后的字节(null-表示classLongName所代表的文件不应该被解密)
      */
     public static byte[] process(String projectPath, String classWinterInfoDir, String classLongName, char[] password) {
-        classWinterInfoDir = StrUtil.isBlank(classWinterInfoDir) ? Constant.DEFAULT_ENCRYPTED_CLASSES_SAVE_DIR : classWinterInfoDir;
+        classWinterInfoDir = StrUtil.isBlank(classWinterInfoDir) ? Constant.MANIFEST_FILE : classWinterInfoDir;
         // 读取文件
         byte[] bytes = IOUtil.readFileFromWorkbenchRoot(new File(projectPath), classWinterInfoDir + classLongName);
         // 检查密码一致性
@@ -125,9 +125,7 @@ public class DecryptExecutor {
                                 }
                                 Arrays.stream(checklist.split(","))
                                         .map(String::trim)
-                                        .forEach(nonSuffixClassLongName -> {
-                                            checklistOfAllLibsMap.put(nonSuffixClassLongName, libDirRelativePath);
-                                        });
+                                        .forEach(nonSuffixClassLongName -> checklistOfAllLibsMap.put(nonSuffixClassLongName, libDirRelativePath));
                             } else {
                                 throw new ClassWinterException("checklistOfAllLibsContent Incorrect format.");
                             }
@@ -233,7 +231,7 @@ public class DecryptExecutor {
      */
     private static char[] obtainAutoGeneratedPwdWhileEncrypt(String projectPath, String classWinterInfoDir) {
         // 项目本身
-        if (classWinterInfoDir.equals(Constant.DEFAULT_ENCRYPTED_CLASSES_SAVE_DIR)) {
+        if (classWinterInfoDir.equals(Constant.MANIFEST_FILE)) {
             if (Cache.passwordCache != null) {
                 // 从缓存读取
                 return Cache.passwordCache;

+ 133 - 30
class-winter-core/src/main/java/winter/com/ideaaedi/classwinter/executor/EncryptExecutor.java

@@ -3,14 +3,20 @@ package winter.com.ideaaedi.classwinter.executor;
 import javassist.CannotCompileException;
 import javassist.ClassPool;
 import javassist.NotFoundException;
+import org.dom4j.Document;
+import org.dom4j.Element;
+import org.dom4j.io.SAXReader;
+import org.dom4j.io.XMLWriter;
 import winter.com.ideaaedi.classwinter.Reverses;
 import winter.com.ideaaedi.classwinter.author.JustryDeng;
 import winter.com.ideaaedi.classwinter.exception.ClassWinterException;
 import winter.com.ideaaedi.classwinter.util.Cache;
 import winter.com.ideaaedi.classwinter.util.Constant;
 import winter.com.ideaaedi.classwinter.util.EncryptUtil;
+import winter.com.ideaaedi.classwinter.util.ExceptionUtil;
 import winter.com.ideaaedi.classwinter.util.IOUtil;
 import winter.com.ideaaedi.classwinter.util.JarUtil;
+import winter.com.ideaaedi.classwinter.util.JavaagentCmdArgs;
 import winter.com.ideaaedi.classwinter.util.JavassistUtil;
 import winter.com.ideaaedi.classwinter.util.Logger;
 import winter.com.ideaaedi.classwinter.util.Pair;
@@ -18,12 +24,14 @@ import winter.com.ideaaedi.classwinter.util.PathUtil;
 import winter.com.ideaaedi.classwinter.util.StrUtil;
 
 import java.io.File;
+import java.io.FileOutputStream;
 import java.nio.charset.StandardCharsets;
 import java.security.SecureRandom;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -37,27 +45,32 @@ import java.util.stream.Collectors;
  */
 public class EncryptExecutor {
     
+    /**
+     * 调用EncryptExecutor进行加密的“人”是否是maven插件
+     */
+    public static boolean invokerIsPlugin = false;
+    
     /** 本项目(class-winter)需要打包的代码 */
     public static final Set<String> CLASS_WINTER_FILES = new HashSet<>();
     
     static {
-        CLASS_WINTER_FILES.add("Cache.class");
-        CLASS_WINTER_FILES.add("JustryDeng.class");
-        CLASS_WINTER_FILES.add("ClassWinterException.class");
-        CLASS_WINTER_FILES.add("DecryptExecutor.class");
-        CLASS_WINTER_FILES.add("Constant.class");
-        CLASS_WINTER_FILES.add("EncryptUtil.class");
-        CLASS_WINTER_FILES.add("ExceptionUtil.class");
-        CLASS_WINTER_FILES.add("IOUtil.class");
-        CLASS_WINTER_FILES.add("JarUtil.class");
-        CLASS_WINTER_FILES.add("JavaagentCmdArgs.class");
-        CLASS_WINTER_FILES.add("JavassistUtil.class");
-        CLASS_WINTER_FILES.add("Logger.class");
-        CLASS_WINTER_FILES.add("Pair.class");
-        CLASS_WINTER_FILES.add("PathUtil.class");
-        CLASS_WINTER_FILES.add("StrUtil.class");
-        CLASS_WINTER_FILES.add("Reverses.class");
-        CLASS_WINTER_FILES.add("Reverses$1.class");
+        CLASS_WINTER_FILES.add(Cache.class.getName().replace(".", "/"));
+        CLASS_WINTER_FILES.add(JustryDeng.class.getName().replace(".", "/"));
+        CLASS_WINTER_FILES.add(ClassWinterException.class.getName().replace(".", "/"));
+        CLASS_WINTER_FILES.add(DecryptExecutor.class.getName().replace(".", "/"));
+        CLASS_WINTER_FILES.add(Constant.class.getName().replace(".", "/"));
+        CLASS_WINTER_FILES.add(EncryptUtil.class.getName().replace(".", "/"));
+        CLASS_WINTER_FILES.add(ExceptionUtil.class.getName().replace(".", "/"));
+        CLASS_WINTER_FILES.add(IOUtil.class.getName().replace(".", "/"));
+        CLASS_WINTER_FILES.add(JarUtil.class.getName().replace(".", "/"));
+        CLASS_WINTER_FILES.add(JavaagentCmdArgs.class.getName().replace(".", "/"));
+        CLASS_WINTER_FILES.add(JavassistUtil.class.getName().replace(".", "/"));
+        CLASS_WINTER_FILES.add(Logger.class.getName().replace(".", "/"));
+        CLASS_WINTER_FILES.add(Pair.class.getName().replace(".", "/"));
+        CLASS_WINTER_FILES.add(PathUtil.class.getName().replace(".", "/"));
+        CLASS_WINTER_FILES.add(StrUtil.class.getName().replace(".", "/"));
+        CLASS_WINTER_FILES.add(Reverses.class.getName().replace(".", "/"));
+        CLASS_WINTER_FILES.add(Cache.class.getName().replace(".", "/").replace("Reverses.class", "Reverses$1.class"));
     }
     
     /** 待加密的的jar/war包路径(如" /tmp/abc.jar) */
@@ -188,7 +201,7 @@ public class EncryptExecutor {
         List<File> allNeedEncryptedClassFileList = filterClasses(allFiles);
         // step3.1. 根据原.class文件,生成加密后的.class文件,并存至Constant.ENCRYPTED_CLASSES_SAVE_DIR
         List<String> allAlreadyEncryptedClassFileList = encryptClasses(allNeedEncryptedClassFileList, new File(targetRootDir,
-                Constant.DEFAULT_ENCRYPTED_CLASSES_SAVE_DIR));
+                Constant.MANIFEST_FILE));
         // step3.2. 生成记录已加密class的全类名的清单文件
         generateChecklistFile(allAlreadyEncryptedClassFileList);
         
@@ -197,26 +210,109 @@ public class EncryptExecutor {
 
         // step5. 混淆原.class文件(即:清空方法体)
         clearClassMethod(allNeedEncryptedClassFileList);
+    
+        // step6. 清除META-INF/maven下pom.xml中关于class-winter-plugin的相关信息
+        clearWinterPluginInfo();
         
-        // step6. 添加class-winter的用于javaagent解密的代码
+        // step7. 添加class-winter的用于javaagent解密的代码
         addClassWinterAgent();
-    
-        // step7. 汇总那些在本次加密前本身就已经是被class-winter混淆的lib的相关信息到当前项目中
+        
+        // step8. 汇总那些在本次加密前本身就已经是被class-winter混淆的lib的相关信息到当前项目中
         collectAlreadyProtectedLibInfo();
         
-        // step8. 与step1项对应,将临时目录还原为原来的lib(此时得到的lib是加密后的)
+        // step9. 与step1项对应,将临时目录还原为原来的lib(此时得到的lib是加密后的)
         doLibJar();
         
-        // step9. 压缩targetRootDir目录为绝对文件路径名为generatedJarWar的jar(or war)包
+        // step10. 压缩targetRootDir目录为绝对文件路径名为generatedJarWar的jar(or war)包
         String generatedJarWar = generateJarWarPath(this.originIsJar);
         JarUtil.doJarWar(targetRootDir, generatedJarWar);
         
-        // step10. 删除临时目录
+        // step11. 删除临时目录
         IOUtil.delete(targetRootDirFile);
-        
         return generatedJarWar;
     }
     
+    /**
+     * 清除META-INF/maven下pom.xml中关于class-winter-plugin的相关信息
+     *
+     * <p>
+     *
+     * <?xml version="1.0" encoding="UTF-8"?>
+     * <project ...>
+     *
+     *     ......
+     *
+     *     <build>
+     *         <plugins>
+     *         	// 要把这部分清除 start
+     *             <plugin >
+     *                 <groupId>com.idea-aedi</groupId>
+     *                 <artifactId>class-winter-maven-plugin</artifactId>
+     *                 ...
+     *             </plugin>
+     *             // 要把这部分清除 end
+     *         </plugins>
+     *     </build>
+     *
+     * </project>
+     */
+    private void clearWinterPluginInfo() {
+        // 只有调用者是插件时,才去清除pom.xml中的class_winter-plugin插件信息
+        if (!invokerIsPlugin) {
+            return;
+        }
+        // 清除META-INF/maven下pom.xml中关于class-winter-plugin的相关信息
+        IOUtil.listFileOnly(new File(this.targetRootDir, Constant.POM_XML_ROOT), "pom.xml").stream()
+                .filter(x -> "pom.xml".equals(x.getName())).forEach(pomFile -> {
+            SAXReader saxReader = new SAXReader();
+            FileOutputStream fileOutputStream = null;
+            try {
+                Document document = saxReader.read(pomFile);
+                // rootElement就是上面的<project></project>
+                Element projectElement = document.getRootElement();
+                if (projectElement == null) {
+                    return;
+                }
+                Element buildElement = projectElement.element("build");
+                if (buildElement == null) {
+                    return;
+                }
+                Element pluginsElement = buildElement.element("plugins");
+                if (pluginsElement == null) {
+                    return;
+                }
+                @SuppressWarnings("unchecked")
+                Iterator<Element> iterator = (Iterator<Element>)pluginsElement.elementIterator();
+                while (iterator.hasNext()) {
+                    Element pluginElement = iterator.next();
+                    Element groupIdElement = pluginElement.element("groupId");
+                    if (groupIdElement == null || groupIdElement.getStringValue() == null
+                            || !Constant.GROUP_ID.equals(groupIdElement.getStringValue().trim())) {
+                        continue;
+                    }
+                    Element artifactIdElement = pluginElement.element("artifactId");
+                    if (artifactIdElement == null || artifactIdElement.getStringValue() == null
+                            || !Constant.ARTIFACT_ID.equals(artifactIdElement.getStringValue().trim())) {
+                        continue;
+                    }
+                    pluginsElement.remove(pluginElement);
+                }
+                
+                // 删除原文件
+                IOUtil.delete(pomFile);
+                // 再生成
+                fileOutputStream = new FileOutputStream(pomFile);
+                XMLWriter xmlwriter = new XMLWriter(fileOutputStream);
+                xmlwriter.write(document);
+                xmlwriter.flush();
+            } catch (Exception e) {
+                throw new ClassWinterException("Delete class-winter-plugin info at pom.xml fail.", e);
+            } finally {
+                IOUtil.close(fileOutputStream);
+            }
+        });
+    }
+    
     /**
      * 采集本来就已经被class-winter混淆了的lib的信息
      */
@@ -238,8 +334,9 @@ public class EncryptExecutor {
                 return;
             }
             // 形如: META-INF/winter/abc-1.0.0_jar/
-            String dirRelativePathForLib = Constant.DEFAULT_ENCRYPTED_CLASSES_SAVE_DIR + libJarName.substring(0, libJarName.length() - 4) + "_jar" + Constant.LINUX_FILE_SEPARATOR;
-            String dirAbsolutePathForLib = this.targetRootDir + File.separator + Constant.DEFAULT_ENCRYPTED_CLASSES_SAVE_DIR + libJarName.substring(0, libJarName.length() - 4) + "_jar" + File.separator;
+            String nonSuffixLibName = libJarName.substring(0, libJarName.length() - 4);
+            String dirRelativePathForLib = Constant.MANIFEST_FILE + nonSuffixLibName + "_jar" + Constant.LINUX_FILE_SEPARATOR;
+            String dirAbsolutePathForLib = this.targetRootDir + File.separator + Constant.MANIFEST_FILE + nonSuffixLibName + "_jar" + File.separator;
     
             /*
              * my-project依赖的lib包本身可以是被class-winter混淆后的,但是这个lib包依赖的lib包不能是被class-winter混淆后
@@ -269,7 +366,7 @@ public class EncryptExecutor {
                 String[] libClassesArr = libChecklist.split(",");
                 byte[] libClazzByte;
                 for (String nonSuffixClassLongName : libClassesArr) {
-                    libClazzByte = IOUtil.readFileFromWorkbenchRoot(lib, Constant.DEFAULT_ENCRYPTED_CLASSES_SAVE_DIR + nonSuffixClassLongName);
+                    libClazzByte = IOUtil.readFileFromWorkbenchRoot(lib, Constant.MANIFEST_FILE + nonSuffixClassLongName);
                     IOUtil.toFile(libClazzByte, new File(dirAbsolutePathForLib, nonSuffixClassLongName), true);
                 }
             }
@@ -305,7 +402,7 @@ public class EncryptExecutor {
                 }
             }
             // 存时,加密存进去
-            String encryptedPassword =EncryptUtil.encrypt(password, Cache.sealCache.toCharArray());
+            String encryptedPassword =EncryptUtil.encrypt(password, Constant.SEAL.toCharArray());
             IOUtil.writeContentToFile(encryptedPassword, new File(dirAbsolutePathForLib, Constant.PWD_WINTER_SIMPLE_NAME));
             // 由于这里已经处理了,将所有lib的密码(不论当初加密lib时密码是用户主动输入的还是系统自动产生的),都当做系统自动产生的进行录入,所以这里写死为false
             IOUtil.writeContentToFile("false", new File(dirAbsolutePathForLib, Constant.USER_IF_INPUT_PWD_SIMPLE_NAME));
@@ -358,6 +455,13 @@ public class EncryptExecutor {
             libJarAndTmpDirMap.put(jarAbsolutePath, temDir);
             // 删除原来的lib包
             IOUtil.delete(new File(jarAbsolutePath));
+            // 擦除MANIFEST.MF中的Premain-Class信息, 如果有的话
+            File jarManifestFile = new File(temDir, Constant.MANIFEST_FILE);
+            if (jarManifestFile.exists()) {
+                String content = IOUtil.readContentFromFile(jarManifestFile);
+                content = content.replace("Premain-Class: " + Reverses.class.getName(), "");
+                IOUtil.writeContentToFile(content, jarManifestFile);
+            }
         });
     }
     
@@ -673,7 +777,6 @@ public class EncryptExecutor {
             return this;
         }
         
-        
         public Builder supportFile(String supportFile) {
             this.supportFile = supportFile;
             return this;

+ 1 - 1
class-winter-core/src/main/java/winter/com/ideaaedi/classwinter/pakage-info.java

@@ -1,4 +1,4 @@
 package winter.com.ideaaedi.classwinter;
 /*
- * 对class-final进行整理、改造、优化、定制
+ * class加密 & 混淆
  */

+ 30 - 0
class-winter-core/src/main/java/winter/com/ideaaedi/classwinter/util/Constant.java

@@ -38,6 +38,11 @@ public interface Constant {
      */
     String DEFAULT_ENCRYPTED_CLASSES_SAVE_DIR = "META-INF/winter/";
     
+    /**
+     * MANIFEST.MF文件的位置
+     */
+    String MANIFEST_FILE = "META-INF/MANIFEST.MF";
+    
     /**
      * 记录已加密.class的全类名的清单文件
      */
@@ -58,6 +63,11 @@ public interface Constant {
      */
     String SEAL_FILE_SIMPLE_NAME = "seal.winter";
     
+    /**
+     * pom.xml文件所在的祖辈目录
+     */
+    String POM_XML_ROOT = "META-INF/maven";
+    
     /**
      * 汇总记录项目中那些本身就已经被class-winter混淆了的lib的checklist
      */
@@ -147,4 +157,24 @@ public interface Constant {
      * 换行符
      */
     String LINE_SEPARATOR = "\r\n";
+    
+    /**
+     * 空格
+     */
+    String WHITE_SPACE = " ";
+    
+    /**
+     * 10
+     */
+    int TEN = 10;
+    
+    /**
+     * groupId
+     */
+    String GROUP_ID = "com.idea-aedi";
+    
+    /**
+     * artifactId
+     */
+    String ARTIFACT_ID = "class-winter-maven-plugin";
 }

+ 1 - 0
class-winter-core/src/main/java/winter/com/ideaaedi/classwinter/util/EncryptUtil.java

@@ -158,6 +158,7 @@ public final class EncryptUtil {
      * @return MD5加密结果
      * @throws NoSuchAlgorithmException 无此算法时抛出
      */
+    @SuppressWarnings("SameParameterValue")
     private static String md5(byte[] source, boolean abbreviation, boolean upperCase) throws NoSuchAlgorithmException {
         // 1. 获取MessageDigest对象
         MessageDigest digest = MessageDigest.getInstance("md5");

+ 17 - 11
class-winter-core/src/main/java/winter/com/ideaaedi/classwinter/util/JarUtil.java

@@ -117,13 +117,17 @@ public final class JarUtil {
      *            解压后文件放置的文件夹
      * @param delOldTargetDirIfAlreadyExist
      *            若targetDir已存在,是否先将原来的targetDir进行删除
-     * @param includeFiles
-     *            只解压指定的这些文件(若为null或者长度为0, 则解压所有文件)   如: ["MANIFEST.MF", "Abc.class"]
+     * @param entryNamePrefixes
+     *            只有当entryName为指定的前缀时,才对该entry进行解压(若为null或者长度为0, 则解压所有文件)   如: ["BOOT-INF/classes/", "BOOT-INF/classes/com/example/ssm/author/JustryDeng.class"]
+     *            <br/>
+     *            注:当entry对应jar或者war中的目录时,那么其值形如 BOOT-INF/classes/
+     *            <br/>
+     *            注:当entry对应jar或者war中的文件时,那么其值形如 BOOT-INF/classes/com/example/ssm/author/JustryDeng.class
      * @return  解压出来的文件(包含目录)的完整路径
      */
     public static <T extends Collection<String>> List<String> unJarWar(String jarWarPath, String targetDir,
                                                                        boolean delOldTargetDirIfAlreadyExist,
-                                                                       T includeFiles) {
+                                                                       T entryNamePrefixes) {
         List<String> list = new ArrayList<>();
         File target = new File(targetDir);
         if (delOldTargetDirIfAlreadyExist) {
@@ -139,21 +143,23 @@ public final class JarUtil {
             Enumeration<? extends ZipEntry> entries = zipFile.entries();
             while (entries.hasMoreElements()) {
                 entry = entries.nextElement();
+                String entryName = entry.getName();
+                // 若entryNamePrefixes不为空,则不解压前缀不匹配的文件或文件夹
+                if (entryNamePrefixes != null && entryNamePrefixes.size() > 0
+                        && entryNamePrefixes.stream().noneMatch(entryName::startsWith)) {
+                    continue;
+                }
                 if (entry.isDirectory()) {
-                    targetFile = new File(target, entry.getName());
+                    targetFile = new File(target, entryName);
                     guarantyDirExist(targetFile);
                 } else {
                     // 有时遍历时,文件先于文件夹出来,所以也得保证目录存在
-                    int lastSeparatorIndex = entry.getName().lastIndexOf(Constant.LINUX_FILE_SEPARATOR);
+                    int lastSeparatorIndex = entryName.lastIndexOf(Constant.LINUX_FILE_SEPARATOR);
                     if (lastSeparatorIndex > 0) {
-                        guarantyDirExist(new File(target, entry.getName().substring(0, lastSeparatorIndex)));
+                        guarantyDirExist(new File(target, entryName.substring(0, lastSeparatorIndex)));
                     }
                     // 解压文件
-                    targetFile = new File(target, entry.getName());
-                    // 若includeFiles不为空,则跳过未包含的文件
-                    if (includeFiles != null && includeFiles.size() > 0 && !includeFiles.contains(targetFile.getName())) {
-                        continue;
-                    }
+                    targetFile = new File(target, entryName);
                     byte[] bytes = IOUtil.toBytes(zipFile.getInputStream(entry));
                     IOUtil.toFile(bytes, targetFile, true);
                     list.add(targetFile.getAbsolutePath());

+ 1 - 1
class-winter-core/src/main/java/winter/com/ideaaedi/classwinter/util/JavaagentCmdArgs.java

@@ -59,7 +59,7 @@ public class JavaagentCmdArgs {
         if (args == null) {
             return new JavaagentCmdArgs();
         }
-        if (args.contains(" ")) {
+        if (args.contains(Constant.WHITE_SPACE)) {
             throw new ClassWinterException("-javaagent args [" + args + "] cannot contain whitespace.");
         }
         // args形如 k1=v1,k2=v2

+ 16 - 16
class-winter-core/src/main/java/winter/com/ideaaedi/classwinter/util/RsaUtil.java

@@ -106,20 +106,20 @@ public class RsaUtil {
         }
     }
     
-//    /**
-//     * test
-//     */
-//    public static void main(String[] args) throws Exception {
-//        //生成公钥和私钥
-//        Pair<String, String> keyPair = genKeyPair();
-//        //加密字符串
-//        String message = "hello JustryDeng";
-//
-//        System.out.println("随机生成的公钥为: " + keyPair.getLeft());
-//        System.out.println("随机生成的私钥为: " + keyPair.getRight());
-//        String cipherText = encrypt(message, keyPair.getLeft());
-//        System.out.println(message + "\t加密后的字符串为: " + cipherText);
-//        String plainText = decrypt(cipherText, keyPair.getRight());
-//        System.out.println("还原后的字符串为: " + plainText);
-//    }
+    /**
+     * test
+     */
+    public static void main(String[] args) throws Exception {
+        //生成公钥和私钥
+        Pair<String, String> keyPair = genKeyPair();
+        //加密字符串
+        String message = "hello JustryDeng";
+
+        System.out.println("随机生成的公钥为: " + keyPair.getLeft());
+        System.out.println("随机生成的私钥为: " + keyPair.getRight());
+        String cipherText = encrypt(message, keyPair.getLeft());
+        System.out.println(message + "\t加密后的字符串为: " + cipherText);
+        String plainText = decrypt(cipherText, keyPair.getRight());
+        System.out.println("还原后的字符串为: " + plainText);
+    }
 }

+ 71 - 0
class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/AlreadyProtectedLibs_Test.java

@@ -0,0 +1,71 @@
+package winter.com.ideaaedi.classwinter;
+
+import winter.com.ideaaedi.classwinter.author.JustryDeng;
+import winter.com.ideaaedi.classwinter.executor.EncryptExecutor;
+import winter.com.ideaaedi.classwinter.util.BashUtil;
+import winter.com.ideaaedi.classwinter.util.Constant;
+import winter.com.ideaaedi.classwinter.util.PathUtil;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 测试originJarOrWar
+ *
+ * 场景说明:
+ *     项目my-project-with-encrypted-lib-no-pwd中依赖了lib包,但是这个lib包是被class-winter混淆了的,
+ *     那么在对my-project-with-encrypted-lib-no-pwd进行打包时,就需要指定alreadyProtectedLibs
+ *     以使用maven插件进行加密为例:
+ *     <plugin>
+ *         <groupId>com.idea-aedi</groupId>
+ *         <artifactId>class-winter-maven-plugin</artifactId>
+ *         <version>1.0.0</version>
+ *         <configuration>
+ *             <finalName>my-project-with-encrypted-lib-no-pwd</finalName>
+ *             <!-- 如果项目my-project-with-encrypted-lib-no-pwd本身中没有任何类需要混淆,那么这里随便写一个就行 -->
+ *             <includePrefix>non-exist</includePrefix>
+ *             <alreadyProtectedLibs>encrypted-lib-no-pwd-1.0.0.jar</alreadyProtectedLibs>
+ *         </configuration>
+ *         <executions>
+ *             <execution>
+ *                 <phase>package</phase>
+ *                 <goals>
+ *                     <goal>class-winter</goal>
+ *                 </goals>
+ *             </execution>
+ *         </executions>
+ *     </plugin>
+ *
+ * @author {@link JustryDeng}
+ * @since 2021/6/12 14:34:45
+ */
+public class AlreadyProtectedLibs_Test {
+    
+    public static void main(String[] args) {
+        String projectRootDir = PathUtil.getProjectRootDir(AlreadyProtectedLibs_Test.class);
+        
+        // 加密
+        EncryptExecutor encryptExecutor = EncryptExecutor.builder()
+                .originJarOrWar(projectRootDir + Constant.LINUX_FILE_SEPARATOR + "my-project-with-encrypted-lib-no-pwd.jar")
+                // includePrefix字段是必填的,但是我们项目(my-project-with-encrypted-lib-no-pwd.jar)本身是没有混淆的,
+                // 只是其中的lib(encrypted-lib-no-pwd-1.0.0.jar)混淆了,我们项目是没必要进行解密的,所以这里值随便填什么都可以的
+                .includePrefix("non-exist")
+                .alreadyProtectedLibs("encrypted-lib-no-pwd-1.0.0.jar")
+                .build();
+        String encryptedJar = encryptExecutor.process();
+        System.out.println(encryptedJar);
+        
+        // (解密)启动
+        // 使用javaagent运行加密后的jar,测试
+        String javaagentArgs = "";
+//        String javaagentArgs = "=debug=true,password=xxx";
+        BashUtil.runCmdAndPrint(String.format("java -javaagent:%s%s -jar %s", encryptedJar, javaagentArgs, encryptedJar));
+
+        try {
+            TimeUnit.SECONDS.sleep(3);
+        } catch (InterruptedException e) {
+            // ignore
+        }
+        // 杀下进程(以防下一个测试方法启动jar时因为端口被占用启动不起来)
+        BashUtil.killProcessByPorts("8080");
+    }
+}

+ 44 - 0
class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/Debug_Test.java

@@ -0,0 +1,44 @@
+package winter.com.ideaaedi.classwinter;
+
+import winter.com.ideaaedi.classwinter.author.JustryDeng;
+import winter.com.ideaaedi.classwinter.executor.EncryptExecutor;
+import winter.com.ideaaedi.classwinter.util.BashUtil;
+import winter.com.ideaaedi.classwinter.util.Constant;
+import winter.com.ideaaedi.classwinter.util.PathUtil;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 测试originJarOrWar
+ *
+ * @author {@link JustryDeng}
+ * @since 2021/6/12 14:34:45
+ */
+public class Debug_Test {
+    
+    public static void main(String[] args) {
+        String projectRootDir = PathUtil.getProjectRootDir(Debug_Test.class);
+        
+        // 加密
+        EncryptExecutor encryptExecutor = EncryptExecutor.builder()
+                .originJarOrWar(projectRootDir + Constant.LINUX_FILE_SEPARATOR + "boot-jar.jar")
+                .includePrefix("non-exist")
+                .build();
+        String encryptedJar = encryptExecutor.process();
+        System.out.println(encryptedJar);
+        
+        // (解密)启动
+        // 使用javaagent运行加密后的jar,测试
+        String javaagentArgs = "";
+        //String javaagentArgs = "=debug=true,password=xxx";
+        BashUtil.runCmdAndPrint(String.format("java -javaagent:%s%s -jar %s", encryptedJar, javaagentArgs, encryptedJar));
+
+        try {
+            TimeUnit.SECONDS.sleep(3);
+        } catch (InterruptedException e) {
+            // ignore
+        }
+        // 杀下进程(以防下一个测试方法启动jar时因为端口被占用启动不起来)
+        BashUtil.killProcessByPorts("8080");
+    }
+}

+ 44 - 0
class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/ExcludePrefix_Test.java

@@ -0,0 +1,44 @@
+package winter.com.ideaaedi.classwinter;
+
+import winter.com.ideaaedi.classwinter.author.JustryDeng;
+import winter.com.ideaaedi.classwinter.executor.EncryptExecutor;
+import winter.com.ideaaedi.classwinter.util.BashUtil;
+import winter.com.ideaaedi.classwinter.util.Constant;
+import winter.com.ideaaedi.classwinter.util.PathUtil;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 测试originJarOrWar
+ *
+ * @author {@link JustryDeng}
+ * @since 2021/6/12 14:34:45
+ */
+public class ExcludePrefix_Test {
+    
+    public static void main(String[] args) {
+        String projectRootDir = PathUtil.getProjectRootDir(ExcludePrefix_Test.class);
+        
+        // 加密
+        EncryptExecutor encryptExecutor = EncryptExecutor.builder()
+                .originJarOrWar(projectRootDir + Constant.LINUX_FILE_SEPARATOR + "boot-jar.jar")
+                .includePrefix("non-exist")
+                .build();
+        String encryptedJar = encryptExecutor.process();
+        System.out.println(encryptedJar);
+        
+        // (解密)启动
+        // 使用javaagent运行加密后的jar,测试
+        String javaagentArgs = "";
+        //String javaagentArgs = "=debug=true,password=xxx";
+        BashUtil.runCmdAndPrint(String.format("java -javaagent:%s%s -jar %s", encryptedJar, javaagentArgs, encryptedJar));
+
+        try {
+            TimeUnit.SECONDS.sleep(3);
+        } catch (InterruptedException e) {
+            // ignore
+        }
+        // 杀下进程(以防下一个测试方法启动jar时因为端口被占用启动不起来)
+        BashUtil.killProcessByPorts("8080");
+    }
+}

+ 44 - 0
class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/FinalName_Test.java

@@ -0,0 +1,44 @@
+package winter.com.ideaaedi.classwinter;
+
+import winter.com.ideaaedi.classwinter.author.JustryDeng;
+import winter.com.ideaaedi.classwinter.executor.EncryptExecutor;
+import winter.com.ideaaedi.classwinter.util.BashUtil;
+import winter.com.ideaaedi.classwinter.util.Constant;
+import winter.com.ideaaedi.classwinter.util.PathUtil;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 测试originJarOrWar
+ *
+ * @author {@link JustryDeng}
+ * @since 2021/6/12 14:34:45
+ */
+public class FinalName_Test {
+    
+    public static void main(String[] args) {
+        String projectRootDir = PathUtil.getProjectRootDir(FinalName_Test.class);
+        
+        // 加密
+        EncryptExecutor encryptExecutor = EncryptExecutor.builder()
+                .originJarOrWar(projectRootDir + Constant.LINUX_FILE_SEPARATOR + "boot-jar.jar")
+                .includePrefix("non-exist")
+                .build();
+        String encryptedJar = encryptExecutor.process();
+        System.out.println(encryptedJar);
+        
+        // (解密)启动
+        // 使用javaagent运行加密后的jar,测试
+        String javaagentArgs = "";
+        //String javaagentArgs = "=debug=true,password=xxx";
+        BashUtil.runCmdAndPrint(String.format("java -javaagent:%s%s -jar %s", encryptedJar, javaagentArgs, encryptedJar));
+
+        try {
+            TimeUnit.SECONDS.sleep(3);
+        } catch (InterruptedException e) {
+            // ignore
+        }
+        // 杀下进程(以防下一个测试方法启动jar时因为端口被占用启动不起来)
+        BashUtil.killProcessByPorts("8080");
+    }
+}

+ 44 - 0
class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/IncludeLibs_Test.java

@@ -0,0 +1,44 @@
+package winter.com.ideaaedi.classwinter;
+
+import winter.com.ideaaedi.classwinter.author.JustryDeng;
+import winter.com.ideaaedi.classwinter.executor.EncryptExecutor;
+import winter.com.ideaaedi.classwinter.util.BashUtil;
+import winter.com.ideaaedi.classwinter.util.Constant;
+import winter.com.ideaaedi.classwinter.util.PathUtil;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 测试originJarOrWar
+ *
+ * @author {@link JustryDeng}
+ * @since 2021/6/12 14:34:45
+ */
+public class IncludeLibs_Test {
+    
+    public static void main(String[] args) {
+        String projectRootDir = PathUtil.getProjectRootDir(IncludeLibs_Test.class);
+        
+        // 加密
+        EncryptExecutor encryptExecutor = EncryptExecutor.builder()
+                .originJarOrWar(projectRootDir + Constant.LINUX_FILE_SEPARATOR + "boot-jar.jar")
+                .includePrefix("non-exist")
+                .build();
+        String encryptedJar = encryptExecutor.process();
+        System.out.println(encryptedJar);
+        
+        // (解密)启动
+        // 使用javaagent运行加密后的jar,测试
+        String javaagentArgs = "";
+        //String javaagentArgs = "=debug=true,password=xxx";
+        BashUtil.runCmdAndPrint(String.format("java -javaagent:%s%s -jar %s", encryptedJar, javaagentArgs, encryptedJar));
+
+        try {
+            TimeUnit.SECONDS.sleep(3);
+        } catch (InterruptedException e) {
+            // ignore
+        }
+        // 杀下进程(以防下一个测试方法启动jar时因为端口被占用启动不起来)
+        BashUtil.killProcessByPorts("8080");
+    }
+}

+ 44 - 0
class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/IncludePrefix_Test.java

@@ -0,0 +1,44 @@
+package winter.com.ideaaedi.classwinter;
+
+import winter.com.ideaaedi.classwinter.author.JustryDeng;
+import winter.com.ideaaedi.classwinter.executor.EncryptExecutor;
+import winter.com.ideaaedi.classwinter.util.BashUtil;
+import winter.com.ideaaedi.classwinter.util.Constant;
+import winter.com.ideaaedi.classwinter.util.PathUtil;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 测试originJarOrWar
+ *
+ * @author {@link JustryDeng}
+ * @since 2021/6/12 14:34:45
+ */
+public class IncludePrefix_Test {
+    
+    public static void main(String[] args) {
+        String projectRootDir = PathUtil.getProjectRootDir(IncludePrefix_Test.class);
+        
+        // 加密
+        EncryptExecutor encryptExecutor = EncryptExecutor.builder()
+                .originJarOrWar(projectRootDir + Constant.LINUX_FILE_SEPARATOR + "boot-jar.jar")
+                .includePrefix("non-exist")
+                .build();
+        String encryptedJar = encryptExecutor.process();
+        System.out.println(encryptedJar);
+        
+        // (解密)启动
+        // 使用javaagent运行加密后的jar,测试
+        String javaagentArgs = "";
+        //String javaagentArgs = "=debug=true,password=xxx";
+        BashUtil.runCmdAndPrint(String.format("java -javaagent:%s%s -jar %s", encryptedJar, javaagentArgs, encryptedJar));
+
+        try {
+            TimeUnit.SECONDS.sleep(3);
+        } catch (InterruptedException e) {
+            // ignore
+        }
+        // 杀下进程(以防下一个测试方法启动jar时因为端口被占用启动不起来)
+        BashUtil.killProcessByPorts("8080");
+    }
+}

+ 5 - 5
class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/ForwardTest.java → class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/MixTest.java

@@ -6,22 +6,22 @@ import winter.com.ideaaedi.classwinter.util.Logger;
 import winter.com.ideaaedi.classwinter.util.PathUtil;
 
 /**
- * 正向加密
+ * 混合测试
  *
  * @author {@link JustryDeng}
  * @since 2021/5/6 23:25:24
  */
-public class ForwardTest {
+public class MixTest {
     
     public static void main(String[] args) {
-        Logger.info(ForwardTest.class, encryptTest());
+        Logger.info(MixTest.class, encryptTest());
     }
     
     /**
      * 加密测试
      */
     public static String encryptTest() {
-        String projectRootDir = PathUtil.getProjectRootDir(ForwardTest.class);
+        String projectRootDir = PathUtil.getProjectRootDir(MixTest.class);
         
         EncryptExecutor encryptExecutor = EncryptExecutor.builder()
                 //(必须)-> 加密spring-boot可执行jar包
@@ -42,7 +42,7 @@ public class ForwardTest {
                 //.finalName("abc-encrypted")
                 
                 // (可选)-> 指定加密密码(若不指定,则系统会自动生成)
-                .password("qwer123~")
+//                .password("qwer123~")
                 
                 // (可选)-> 前缀匹配的方式,指定需要忽略加密的class,用于对includePrefix指定的范围中的目标进行排除
                 // 逗号后面有没有空格都可以

+ 44 - 0
class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/OriginJarOrWar_Test.java

@@ -0,0 +1,44 @@
+package winter.com.ideaaedi.classwinter;
+
+import winter.com.ideaaedi.classwinter.author.JustryDeng;
+import winter.com.ideaaedi.classwinter.executor.EncryptExecutor;
+import winter.com.ideaaedi.classwinter.util.BashUtil;
+import winter.com.ideaaedi.classwinter.util.Constant;
+import winter.com.ideaaedi.classwinter.util.PathUtil;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 测试originJarOrWar
+ *
+ * @author {@link JustryDeng}
+ * @since 2021/6/12 14:34:45
+ */
+public class OriginJarOrWar_Test {
+    
+    public static void main(String[] args) {
+        String projectRootDir = PathUtil.getProjectRootDir(OriginJarOrWar_Test.class);
+        
+        // 加密
+        EncryptExecutor encryptExecutor = EncryptExecutor.builder()
+                .originJarOrWar(projectRootDir + Constant.LINUX_FILE_SEPARATOR + "boot-jar.jar")
+                .includePrefix("non-exist")
+                .build();
+        String encryptedJar = encryptExecutor.process();
+        System.out.println(encryptedJar);
+        
+        // (解密)启动
+        // 使用javaagent运行加密后的jar,测试
+        String javaagentArgs = "";
+        //String javaagentArgs = "=debug=true,password=xxx";
+        BashUtil.runCmdAndPrint(String.format("java -javaagent:%s%s -jar %s", encryptedJar, javaagentArgs, encryptedJar));
+
+        try {
+            TimeUnit.SECONDS.sleep(3);
+        } catch (InterruptedException e) {
+            // ignore
+        }
+        // 杀下进程(以防下一个测试方法启动jar时因为端口被占用启动不起来)
+        BashUtil.killProcessByPorts("8080");
+    }
+}

+ 1 - 1
class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/ProtectedLibTest.java

@@ -14,7 +14,7 @@ import winter.com.ideaaedi.classwinter.util.PathUtil;
 public class ProtectedLibTest {
     
     public static void main(String[] args) {
-        String projectRootDir = PathUtil.getProjectRootDir(ForwardTest.class);
+        String projectRootDir = PathUtil.getProjectRootDir(MixTest.class);
         EncryptExecutor encryptExecutor = EncryptExecutor.builder()
 //                .originJarOrWar(projectRootDir + "my-project-with-encrypted-lib-no-pwd.jar")
                 .originJarOrWar(projectRootDir + Constant.LINUX_FILE_SEPARATOR + "my-project-with-encrypted-lib-have-pwd.jar")

+ 1 - 1
class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/ReversesTest.java

@@ -53,7 +53,7 @@ public class ReversesTest {
      */
     public static void main(String[] args) {
         // 先生成加密后的jar
-        String encryptedJar = ForwardTest.encryptTest();
+        String encryptedJar = MixTest.encryptTest();
         encryptedJar = new File(encryptedJar).getAbsolutePath();
 
         /// - 解密正常 - 测试

+ 44 - 0
class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/SupportFile_Test.java

@@ -0,0 +1,44 @@
+package winter.com.ideaaedi.classwinter;
+
+import winter.com.ideaaedi.classwinter.author.JustryDeng;
+import winter.com.ideaaedi.classwinter.executor.EncryptExecutor;
+import winter.com.ideaaedi.classwinter.util.BashUtil;
+import winter.com.ideaaedi.classwinter.util.Constant;
+import winter.com.ideaaedi.classwinter.util.PathUtil;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 测试originJarOrWar
+ *
+ * @author {@link JustryDeng}
+ * @since 2021/6/12 14:34:45
+ */
+public class SupportFile_Test {
+    
+    public static void main(String[] args) {
+        String projectRootDir = PathUtil.getProjectRootDir(SupportFile_Test.class);
+        
+        // 加密
+        EncryptExecutor encryptExecutor = EncryptExecutor.builder()
+                .originJarOrWar(projectRootDir + Constant.LINUX_FILE_SEPARATOR + "boot-jar.jar")
+                .includePrefix("non-exist")
+                .build();
+        String encryptedJar = encryptExecutor.process();
+        System.out.println(encryptedJar);
+        
+        // (解密)启动
+        // 使用javaagent运行加密后的jar,测试
+        String javaagentArgs = "";
+        //String javaagentArgs = "=debug=true,password=xxx";
+        BashUtil.runCmdAndPrint(String.format("java -javaagent:%s%s -jar %s", encryptedJar, javaagentArgs, encryptedJar));
+
+        try {
+            TimeUnit.SECONDS.sleep(3);
+        } catch (InterruptedException e) {
+            // ignore
+        }
+        // 杀下进程(以防下一个测试方法启动jar时因为端口被占用启动不起来)
+        BashUtil.killProcessByPorts("8080");
+    }
+}

+ 44 - 0
class-winter-core/src/test/java/winter/com/ideaaedi/classwinter/Tips_Test.java

@@ -0,0 +1,44 @@
+package winter.com.ideaaedi.classwinter;
+
+import winter.com.ideaaedi.classwinter.author.JustryDeng;
+import winter.com.ideaaedi.classwinter.executor.EncryptExecutor;
+import winter.com.ideaaedi.classwinter.util.BashUtil;
+import winter.com.ideaaedi.classwinter.util.Constant;
+import winter.com.ideaaedi.classwinter.util.PathUtil;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 测试originJarOrWar
+ *
+ * @author {@link JustryDeng}
+ * @since 2021/6/12 14:34:45
+ */
+public class Tips_Test {
+    
+    public static void main(String[] args) {
+        String projectRootDir = PathUtil.getProjectRootDir(Tips_Test.class);
+        
+        // 加密
+        EncryptExecutor encryptExecutor = EncryptExecutor.builder()
+                .originJarOrWar(projectRootDir + Constant.LINUX_FILE_SEPARATOR + "boot-jar.jar")
+                .includePrefix("non-exist")
+                .build();
+        String encryptedJar = encryptExecutor.process();
+        System.out.println(encryptedJar);
+        
+        // (解密)启动
+        // 使用javaagent运行加密后的jar,测试
+        String javaagentArgs = "";
+        //String javaagentArgs = "=debug=true,password=xxx";
+        BashUtil.runCmdAndPrint(String.format("java -javaagent:%s%s -jar %s", encryptedJar, javaagentArgs, encryptedJar));
+
+        try {
+            TimeUnit.SECONDS.sleep(3);
+        } catch (InterruptedException e) {
+            // ignore
+        }
+        // 杀下进程(以防下一个测试方法启动jar时因为端口被占用启动不起来)
+        BashUtil.killProcessByPorts("8080");
+    }
+}

BIN
class-winter-core/src/test/resources/boot-jar.jar


BIN
class-winter-core/src/test/resources/my-project-with-encrypted-lib-have-pwd.jar


BIN
class-winter-core/src/test/resources/my-project-with-encrypted-lib-no-pwd.jar


BIN
class-winter-core/src/test/resources/my-project-with-normal-lib.jar


BIN
class-winter-core/src/test/resources/normal-jar.jar


BIN
class-winter-core/src/test/resources/war-project.war


+ 1 - 1
class-winter-maven-plugin/pom.xml

@@ -14,7 +14,7 @@
 
     <dependencies>
         <dependency>
-            <groupId>com.niantou</groupId>
+            <groupId>com.idea-aedi</groupId>
             <artifactId>class-winter-core</artifactId>
             <version>${project.parent.version}</version>
         </dependency>

+ 5 - 4
class-winter-maven-plugin/src/main/java/winter/com/ideaaedi/classwinter/plugin/ClassWinterPlugin.java

@@ -1,9 +1,5 @@
 package winter.com.ideaaedi.classwinter.plugin;
 
-import net.jd.classwinter.Forward;
-import net.jd.classwinter.executor.EncryptExecutor;
-import net.jd.classwinter.util.ExceptionUtil;
-import net.jd.classwinter.util.Logger;
 import org.apache.maven.model.Build;
 import org.apache.maven.plugin.AbstractMojo;
 import org.apache.maven.plugin.MojoExecutionException;
@@ -12,6 +8,10 @@ import org.apache.maven.plugins.annotations.LifecyclePhase;
 import org.apache.maven.plugins.annotations.Mojo;
 import org.apache.maven.plugins.annotations.Parameter;
 import org.apache.maven.project.MavenProject;
+import winter.com.ideaaedi.classwinter.Forward;
+import winter.com.ideaaedi.classwinter.executor.EncryptExecutor;
+import winter.com.ideaaedi.classwinter.util.ExceptionUtil;
+import winter.com.ideaaedi.classwinter.util.Logger;
 
 import java.io.File;
 
@@ -92,6 +92,7 @@ public class ClassWinterPlugin extends AbstractMojo {
         Logger.debug(ClassWinterPlugin.class, "The encrypted executor generated based on your configuration is -> " + encryptExecutor);
         String encryptedJarOrWar;
         try {
+            EncryptExecutor.invokerIsPlugin = true;
             encryptedJarOrWar = encryptExecutor.process();
             Logger.info(ClassWinterPlugin.class, "The absolute path of the obfuscated jar is [" + encryptedJarOrWar + "]");
         } catch (Exception e) {