Skip to content

String replaceAll has a gotcha in JavaTemplate.writeOutJavaFile #2

@Tihamer54

Description

@Tihamer54

Somewhere around line 36 of the class JavaTemplate, method writeOutJavaFile, there is the following line:
String packageDirectory = packageName.replaceAll(".", File.separator);

On most MS Systems, file separator is set to '', so this causes an error if you have a dot/period (.) in your packageName (and most often, you will).
The String replaceAll is a nice and powerful method, but it is overkill here, especially since (as Chris Smith points out at http://www.velocityreviews.com/forums/t127000-replace-period-using-string-replaceall.html) "the second parameter isn't just a String either; it's a pseudo-regexp where most special characters don't work, but subexpression references do. That means, essentially, that you have to be sure to properly escape BOTH parameters to this method (and in consequence, the method is practically useless unless both parameter values are known when the code is written)."

For example, try this bit of code:
String packageName = "com.example3";
String result = packageName.replaceAll(".", File.separator);
System.out.println("result= " + result);
You'll get the following error:
Replacing the period in com.example3 with ''
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 1
at java.lang.String.charAt(String.java:658)
at java.util.regex.Matcher.appendReplacement(Matcher.java:762)
at java.util.regex.Matcher.replaceAll(Matcher.java:906)
at java.lang.String.replaceAll(String.java:2162)
at MyClass.main(MyClass.java:53)

You can fix it by replacing the File.separator, which screws up the Java/regex syntax because of the backslash(), with four backslashes:

      String result = packageName.replaceAll("\\.", "\\\\");

But then the code would break in Linux. OTOH, if you just do a simpler "replace" of "." instead:
String result = packageName.replace(".", File.separator);

Then it works fine. BTW, it works no matter how many dots you have in your packageName (I used to be under the same misconception; that if Java had a replaceAll, then the regular "replace", must only replace the first substring; this is not the case). My output:

  result= com\my\example3

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions