Reputation: 343
Could anyone tell what is wrong with my code ? when using javassist to insert code , it show error "Caused by: compile error: ; is missing"; But I double check , there no ; missing at all. Is there some limitation of javassist here?
ClassPool cp = ClassPool.getDefault();
cp.importPackage("com.mysql.cj");
CtClass cc = cp.get(clzname);
CtMethod ms = cc.getDeclaredMethod(
"execute");
StringBuilder sb = new StringBuilder();
sb.append("String sql = ((PreparedQuery) this.query).getOriginalSql();");
sb.append("QueryBindings bindings = ((PreparedQuery) this.query).getQueryBindings();\n" +
" for (BindValue o : bindings.getBindValues()) {\n" +
" sql = sql.replaceFirst(\"\\\\?\", new String(o.getByteValue()));\n" +
" }");
sb.append(
"System.out.println( sql);");
ms.insertBefore(sb.toString());
byteCode = cc.toBytecode();
Upvotes: 0
Views: 925
Reputation: 343
I solved my bug by replacing the for loop.
It seems javaassit not support convient for loop, it has to be change it into for(int i= 0; i< lenth; i++) format;
And thanks to @kutschem , the code also need to be wrapped by curly braces.
ClassPool cp = ClassPool.getDefault();
cp.importPackage("com.mysql.cj");
CtClass cc = cp.get(clzname);
CtMethod ms = cc.getDeclaredMethod(
"execute");
ms.insertBefore("{\n" +
" String sql = ((PreparedQuery) this.query).getOriginalSql();\n" +
" QueryBindings bindings = ((PreparedQuery) this.query).getQueryBindings();\n" +
" for (int i =0; i < bindings.getBindValues().length; i++ ) sql = sql.replaceFirst(\"\\\\?\", new String(bindings.getBindValues()[i].getByteValue()));\n" +
" System.out.println(sql);\n" +
" }");
byteCode = cc.toBytecode();
Upvotes: 1
Reputation: 67457
In addition to wrapping your code into curly braces like @kutschem said, I also have an idea for you how to concatenate your string more easily, without using a StringBuilder
. As a positive side effect, you also get line breaks:
String codeToBeInserted = String.join("\n",
"{",
" String sql = ((PreparedQuery) this.query).getOriginalSql();",
" QueryBindings bindings = ((PreparedQuery) this.query).getQueryBindings();",
" for (BindValue o : bindings.getBindValues()) {",
" sql = sql.replaceFirst(\"\\\\?\", new String(o.getByteValue()));",
" }",
" System.out.println(sql);",
"}"
);
System.out.println(codeToBeInserted);
String.join
is available since Java 8. The console output would be:
{
String sql = ((PreparedQuery) this.query).getOriginalSql();
QueryBindings bindings = ((PreparedQuery) this.query).getQueryBindings();
for (BindValue o : bindings.getBindValues()) {
sql = sql.replaceFirst("\\?", new String(o.getByteValue()));
}
System.out.println(sql);
}
To me, your code looks okay syntactically, especially the replaceFirst
meant to replace ?
by a fixed value.
Upvotes: 0
Reputation: 8163
The javadoc for insertBefore says:
https://www.javassist.org/html/javassist/CtBehavior.html#insertBefore(java.lang.String)
Parameters: src - the source code representing the inserted bytecode. It must be a single statement or block.
So, wrap the code in curly braces so it is a single block.
Upvotes: 6