开发者

How to use java annotations to modify source code before final compilation?

I've read from the apt tool page that one can create AnnotationProcessors to generate new derived files (source files, class files, deployment descriptor开发者_如何学JAVAs, etc.). I am looking for example to do so.

My need is to encode all annotated strings at compile time, so that reading the class file does not allow reading the static strings:

Base code:

String message = (@Obfuscated "a string that should not be readable in class file");

Should be reworked as:

String message = new ObfuscatedString(new long[] {0x86DD4DBB5166C13DL, 0x4C79B1CDC313AE09L, 0x1A353051DAF6463BL}).toString();

Based on the static ObfuscatedString.obfuscate(String) method of the TrueLicense framework, the processor can generate the code to replace the annotated string. Indeed, this method generates the string "new ObfuscatedString([numeric_code]).toString()". At runtime the toString() method of ObfuscatedString is able to return the string encoded in the numeric code.

Any idea on how to write the process() method of the AnnotationProcessor to edit the annotated code?

Thanks in advance,


You could have

String message = Obfuscated.decode("a string that should not be readable in class file");

which compiles normally, however after compilation you have a tool which examines the bytecode e.g. using ObjectWeb's ASM, changes the String literal so it looks like

String message = Obfuscated.decode("\u86DD\u4DBB\u5166\uC13D\u4C79\uB1CD\uC313\uAE09\u1A35\u3051\uDAF6\u463B");

To make it easer to identify strings which need to be changed, you could add a prefix to them, and you could ensure this prefix does appear after the code has been obfuscated.

String s = "Obfuscate: a string that should not be readable in class file";
// later
String message = Obfuscated.decode(s);


I bet spoon may be what you are looking for. But why do you want to obfuscate static strings?


Zelix KlassMaster offers this ability. If memory serves, it used to be free for companies under 3 developers, but I just checked their purchase page, and it seems that they now charge a small-developers fee for small companies. I haven't used it in several years (at least 5 or 7), but it did a fantastic job obfuscating strings, and code in general.


When I am going to generate the version for distribution it, I have a class that override all the constants with the Ofuscated String call:

This is the process:

  1. I run my ANT, that copy all the code in other place.
  2. The ANT call to OfuscateJavaConstant.
  3. I Compile the code.

The ANT:

 <java classname="de.schlichtherle.util.ObfuscatedString">
     <arg value="${of.constant}" />
     <classpath>
         <pathelement location="${exit.path}/${buildDir}" />
         <path refid="myclasspath" />
     </classpath>
  </java>

The Java Ofuscate code (ObfuscatedString):

public static void main(String[] args) {
    if ( args!=null ){
        String[] ficheros = args[0].split(";");

        if ( args!=ficheros )
            for (String ruta:ficheros)
                ofuscateConstantClass( ruta );
    }
}

private static void ofuscateConstantClass( String fileName ){

    File archivo = null;
    FileReader fr = null;
    BufferedReader br = null;
    List<String> sb  = new ArrayList<String>();
    FileWriter fichero = null;
    PrintWriter pw = null;

    try{
        archivo = new File( fileName );
        fr = new FileReader (archivo);
        br = new BufferedReader(fr);
        String linea;
        while( (linea=br.readLine())!=null ){

            String noWhite = linea.trim().replaceAll(" +", " ");

            if ( noWhite.toLowerCase().startsWith("public static final string") && noWhite.endsWith("\";") ){

                String firstPart = noWhite.substring(0, noWhite.indexOf("\"") );
                String constant = noWhite.substring(noWhite.indexOf("\"")+1, noWhite.lastIndexOf("\"") );
                String ofuscatedConstant = obfuscate( constant );
                String secondPart = noWhite.substring(noWhite.lastIndexOf("\"")+1 );
                sb.add( firstPart + ofuscatedConstant + secondPart );
                System.out.println( constant + "-->" + ofuscatedConstant );
            } else
                sb.add( linea );
        }

        fichero = new FileWriter( fileName );
        pw = new PrintWriter(fichero);
        for (String s:sb)
            pw.println( s );

    } catch ( Exception e){

    } finally {
         try{
             if( null != fr )
                 fr.close();
             if( null != pw )
                 pw.close();
             if( null != fichero )
                 fichero.close();
         }catch (Exception e2){
            e2.printStackTrace();
         }
    }

}

Hope it helps :)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜