Zelix KlassMaster - Documentation

Calling Zelix KlassMaster™ from Apache Maven

Zelix KlassMaster™ exposes a generic Java API that allows it to be called by a build tool. A basic Maven plugin for the Zelix KlassMaster™ obfuscator is built on this API and can be downloaded as zkm-plugin-1.0.4.jar The plugin can be installed into your environment using the following command where pathToDirectory is the absolute path to the directory containing the Zelix KlassMaster JAR ZKM.jar.

mvn org.apache.maven.plugins:maven-install-plugin:2.5.2:install-file -D"file=zkm-plugin-1.0.4.jar" -D"ZKM_HOME=pathToDirectory"

Below there is a simple example pom.xml making use of the plugin and a corresponding ZKM Script. The plugin POM and the source code of the ZelixKlassMasterMojo also appear below.

The parameters to the plugin correspond to the basic command line options. The ZKM Script referred to in the example pom.xml typically makes use of System Variables which are basic project properties or that have been set in the pom XML. Note that when you use a pom which makes use of the Zelix KlassMaster Maven plugin you always need to have the ZKM_HOME system property set to the absolute path to the directory containing the Zelix KlassMaster JAR ZKM.jar as is shown below.

mvn package -D"ZKM_HOME=pathToDirectory"

Note that the project compile artifacts will be appended into a classpath string stored in the compileArtifactPath property. Similarly, the contents of the <classpathLibs> tag will be appended into a classpath string stored in the classpathLibs property.

You can also set Special Configuration Options by setting System properties.

Apache Maven Example POM XML

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.zelix.plugins</groupId>
  <artifactId>test</artifactId>
  <version>1.0.4</version>
  <packaging>jar</packaging>
  <name>Test of ZelixKlassMasterMojo</name>
  <properties>
      <!-- These will be passed through to plugin as project properties -->
      <myProperty0>true</myProperty0>
      <junit.version>4.11</junit.version>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <maven.compiler.target>1.8</maven.compiler.target>
      <maven.compiler.source>1.8</maven.compiler.source>
   </properties>
   <dependencies>
      <dependency>
         <groupId>junit</groupId>
         <artifactId>junit</artifactId>
         <version>${junit.version}</version>
         <scope>compile</scope>
      </dependency>
   </dependencies>
   <build>
   <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>3.1</version>
      <configuration>
         <source>1.8</source>
         <target>1.8</target>
      </configuration>
    </plugin>
    <plugin>
      <groupId>com.zelix.plugins</groupId>
      <artifactId>zkm-plugin</artifactId>
      <version>1.0.4</version>
      <dependencies>
         <dependency>
            <groupId>com.zelix.plugins</groupId>
            <artifactId>ZKM</artifactId>
            <version>20.0.0</version>
            <scope>system</scope>
            <systemPath>${ZKM_HOME}/ZKM.jar</systemPath>
         </dependency>
      </dependencies>
      <executions>
        <execution>
            <phase>package</phase>
            <goals><goal>obfuscate</goal></goals>
        </execution>
      </executions>
      <configuration>
	 <!-- Will be used to inject values into the plugin but will not be in project properties -->
         <isSkip>false</isSkip>
         <scriptFile>script.txt</scriptFile>
         <classpathLibs>
            <lib>${java.home}/lib/rt.jar</lib>
            <lib>D:\Java\apache-ant-1.9.2\lib\ant.jar</lib>
         </classpathLibs>
      </configuration>
    </plugin>
    </plugins>
  </build>
</project>

Example ZKM Script

//System variables shown in blue. These will be replaced with their corresponding values.
classpath "%classpathLibs%"
          "%compileArtifactPath%"
          "%pluginArtifactPath%"
          ;

open "%project.build.directory%%file.separator%%project.build.finalName%.%project.packaging%";

trimExclude *.*^ public static main(java.lang.String[]);

trim;

exclude     *.^*^ public static main(java.lang.String[]);

obfuscate   keepInnerClassInfo=false
            keepGenericsInfo=%myProperty0%
            obfuscateFlow=aggressive
            exceptionObfuscation=heavy
            encryptStringLiterals=flowObfuscate
            ;

saveAll   "%project.build.directory%";

Apache Maven POM for ZelixKlassMasterMojo Plugin

<?xml version="1.0" encoding="UTF-8"?><project>
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.zelix.plugins</groupId>
   <artifactId>zkm-plugin</artifactId>
   <version>1.0.4</version>
   <packaging>maven-plugin</packaging>
   <name>Zelix KlassMaster Plugin</name>
   <description>A Maven plugin for the Zelix KlassMaster Java obfuscator.
                Requires the ZKM_HOME system property to be set to the directory containing the ZKM.jar.
                Zelix KlassMaster is typically licensed to be installed and used on just one computer.
                It will typically not be possible to put it in a repository.
   </description>
   </comments>
   <url>https://www.zelix.com/klassmaster</url>
   <licenses>
      <license>
         <name>GNU General Public License, version 3</name>
         <url>http://www.gnu.org/licenses/gpl-3.0.txt</url>
      </license>
   </licenses>
   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <maven.compiler.target>1.8</maven.compiler.target>
      <maven.compiler.source>1.8</maven.compiler.source>
   </properties>
   <dependencies>
        <dependency>
            <groupId>org.apache.maven</groupId>
            <artifactId>maven-plugin-api</artifactId>
            <version>3.2.3</version>
        </dependency>
      <dependency>
         <groupId>org.apache.maven</groupId>
         <artifactId>maven-project</artifactId>
         <version>2.2.0</version>
         <type>jar</type>
         <optional>false</optional>
      </dependency>
      <dependency>
         <groupId>com.zelix.plugins</groupId>
         <artifactId>ZKM</artifactId>
         <version>20.0.0</version>
         <scope>system</scope>
         <systemPath>${ZKM_HOME}/ZKM.jar</systemPath>
      </dependency>
   </dependencies>
</project>

Zelix KlassMaster Apache Maven Plugin - ZelixKlassMasterMojo

ZelixKlassMasterMojo is a basic Apache Maven mojo for the Zelix KlassMaster™ obfuscator. It passes in the calling pom's properties by default.

/*-----------------------------------------------------------------------------*
 * Copyright 2015-2022 Zelix Pty Ltd (ACN 078 740 093). All  Rights Reserved.  *
 *                                                                             *
 * Licensed under the GNU General Public License, version 3                    *
 * http://www.gnu.org/licenses/gpl-3.0.txt                                     *
 * The license includes the following conditions.                              *
 *                                                                             *
 *  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY           *
 * APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT      *
 * HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY   *
 * OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,    *
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR      *
 * PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM  *
 * IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF    *
 * ALL NECESSARY SERVICING, REPAIR OR CORRECTION.                              *
 *                                                                             *
 * IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING       *
 * WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS   *
 * THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY *
 * GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE    *
 * USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF   *
 * DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD  *
 * PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),    *
 * EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF   *
 * SUCH DAMAGES.                                                               *
 *                                                                             *
 *-----------------------------------------------------------------------------*

package com.zelix.plugins;

import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.project.*;
import org.apache.maven.artifact.*;
import org.apache.maven.model.*;
import java.util.*;
import java.io.*;

/**
 * Allows the Zelix KlassMaster obfuscator to be called as part of a Maven build.
 *
 * @goal obfuscate
 * @phase package
 * @requiresDependencyResolution compile
 * @version 1.0.4
 */
public class ZelixKlassMasterMojo extends AbstractMojo{
 
   /**
   * If true then do not obfuscate.
   *
   * @parameter default-value=false
   */
   private boolean isSkip;
   
   /**
   * A ZKM Script file must be specified.
   *
   * @parameter default-value="${basedir}/script.txt"
   * @required
   */
   private File scriptFile;

   /**
   * Set the log file name. The file name can be relative or absolute. This parameter is optional.
   * The log file name will default to "ZKM_log.txt".
   *
   * @parameter default-value="${basedir}/ZKM_log.txt"
   */
   private String logFileName;

   /**
   * Set the trim log file name. The file name can be relative or absolute. This parameter is optional.
   * The trim log file name will default to "ZKM_TrimLog.txt".
   *
   * @parameter  default-value="${basedir}/ZKM_TrimLog.txt"
   */
   private String trimLogFileName;

   /**
   * Set the 'default exclusions' file name. The file name can be relative or absolute. This parameter is optional.
   * By default Zelix KlassMaster will look for a file named "defaultExclude.txt".
   *
   * @parameter  
   */
   private String defaultExcludeFileName;

   /**
   * Set the 'default trim exclusions' file name. The file name can be relative or absolute. Parameter is optional.
   * By default Zelix KlassMaster will look for a file named "defaultTrimExclude.txt".
   *
   * @parameter 
   */
   private String defaultTrimExcludeFileName;  
   
   /**
   * Set the name of the default directory . The directory name can be relative or absolute.
   * If any of the log file, trim log file, 'default exclusion' file and the 'default trim exclusions' file names
   * are relative then they will be relative to this miscellaneous files directory. This parameter is optional.
   * The directory name will default to that of the "user.dir" system property.
   *
   * @parameter
   */
   private String defaultDirectoryName;

   /**
   * Optional. Defaults to true.
   *
   * @parameter default-value=true
   */
   private boolean isVerbose;

   /**
   * Optional. Defaults to false.
   * If true then Zelix KlassMaster will parse the ZKM Script but not execute it.
   *
   * @parameter default-value=false
   */
   private boolean isParseOnly;

   /**
   * Optional. Any values will be used to be a classpath string which will be stored as 
   * the "classpathLibs" property for use in the ZKM Script via a System Variable.
   *
   * @parameter
   */
   private File[] classpathLibs;

   /**
    * The Maven project reference where the plugin is currently being executed. The default value is populated from maven.
    * https://maven.apache.org/ref/3.2.3/apidocs/org/apache/maven/project/MavenProject.html
    * @parameter expression="${project}"
    * @readonly
    * @required
    */
   protected MavenProject mavenProject;
   
   /**
   * @parameter expression="${project.build.finalName}"
   */
   protected String buildFile;
   
   /**
   * @parameter expression="${project.artifactId}"
   */
   protected String projectArtifactId;
   
   /**
   * @parameter expression="${project.packaging}"
   */
   protected String projectPackaging;
   
   /**
   * @parameter expression="${project.build.outputDirectory}"
   */
   protected String outputDirectory;
   
   /**
   * @parameter expression="${project.build.directory}"
   */
   protected String buildDirectory;
   
   /**
   * @parameter expression="${project.version}"
   */
   protected String projectVersion;
   
   /**
   * @parameter expression="${basedir}"
   */
   protected String basedir;   

   /**
    * The plugin dependencies.
    * 
    * @parameter expression="${plugin.artifacts}"
    * @required
    * @readonly
    */
   protected List pluginArtifacts;

   @Override
   public void execute() throws MojoExecutionException, MojoFailureException {
      Log log = getLog();
      log.info("Zelix KlassMaster Plugin 1.0.4");
      log.info("================================");
      if (isSkip) {
            log.info("Skipping Zelix KlassMaster obfuscation because 'obfuscate.skip' is set to 'true'");
            return;
      }
      if (scriptFile == null) {
         throw new MojoFailureException("ZKM Script file is null");
      }
      if (!scriptFile.exists() || scriptFile.isDirectory()) {
        throw new MojoFailureException("'" + scriptFile.getAbsolutePath() + "' does not exist or is a directory");
      }
 
      Properties extraProperties = new Properties();
       //add project properties to extraProperties
      for(Map.Entry entry : mavenProject.getProperties().entrySet()) {
         extraProperties.put(entry.getKey(), entry.getValue());
      }
      //add configuration parameters to extraProperties mainly for debugging purposes
      extraProperties.put("isSkip", isSkip);
      if(scriptFile!=null)                extraProperties.put("scriptFile", scriptFile.getAbsolutePath());
      if(logFileName!=null)               extraProperties.put("logFileName", logFileName);
      if(trimLogFileName!=null)           extraProperties.put("trimLogFileName", trimLogFileName);
      if(defaultExcludeFileName!=null)    extraProperties.put("defaultExcludeFileName", defaultExcludeFileName);
      if(defaultTrimExcludeFileName!=null)extraProperties.put("defaultTrimExcludeFileName", defaultTrimExcludeFileName);
      if(defaultDirectoryName!=null)      extraProperties.put("defaultDirectoryName", defaultDirectoryName);
      extraProperties.put("isVerbose", isVerbose);
      extraProperties.put("isParseOnly", isParseOnly);
      //add project parameters
      extraProperties.put("basedir", basedir);
      extraProperties.put("project.build.finalName", buildFile);
      extraProperties.put("project.build.directory", buildDirectory);
      extraProperties.put("project.packaging", projectPackaging);
      extraProperties.put("project.build.outputDirectory", outputDirectory);
      extraProperties.put("project.artifactId", projectArtifactId);
      extraProperties.put("project.version", projectVersion);
      StringBuilder libBuilder = new StringBuilder();
      //build a classpath string from classpathLibs
      if (classpathLibs != null && classpathLibs.length > 0) {
         for (File lib : classpathLibs) {
            if (libBuilder.length() > 0) {
               libBuilder.append(File.pathSeparator);
            }
            libBuilder.append(lib.getAbsolutePath());
          }
         extraProperties.put("classpathLibs", libBuilder.toString());
      }
      //build a classpath string from compile artifacts
      StringBuilder compileArtifactBuilder = new StringBuilder();
      for (Object compileArtifact : mavenProject.getCompileArtifacts()) {
         File file = ((Artifact)compileArtifact).getFile();
         if ((file != null) && (file.exists())) {
            if (compileArtifactBuilder.length() > 0) {
               compileArtifactBuilder.append(File.pathSeparator);
            }
            compileArtifactBuilder.append(file.getAbsolutePath());
         }
      }
      extraProperties.put("compileArtifactPath", compileArtifactBuilder.toString());
      //build a classpath string from plugin artifacts
      StringBuilder pluginArtifactBuilder = new StringBuilder();
      Set<String> artifactPathSet = new HashSet<String>();
      for (Iterator i = pluginArtifacts.iterator(); i.hasNext();) {
         String artifactPath = ((Artifact)i.next()).getFile().getAbsolutePath();
         if (artifactPathSet.add(artifactPath)) {
            if (pluginArtifactBuilder.length() > 0) {
               pluginArtifactBuilder.append(File.pathSeparator);
            }
            pluginArtifactBuilder.append(artifactPath);
         }
      }
      extraProperties.put("pluginArtifactPath", pluginArtifactBuilder.toString());
      try {
         com.zelix.ZKM.run(scriptFile.getAbsolutePath(), logFileName, trimLogFileName, defaultExcludeFileName,
		           defaultTrimExcludeFileName, defaultDirectoryName, isVerbose, isParseOnly, extraProperties);
      }
      catch(Exception ex) {
         log.info(ex);
         throw new MojoFailureException(ex.toString());
      }
   }  
}
 
Documentation Table of Contents
Zelix KlassMaster - Java Obfuscator