views:

201

answers:

8

The problem is as follows:

There is a massive codebase in Java (hundreds of files in tens of packages) where we need the ability to add and remove the keyword strictfp in each class definition. I am planning to use either sed or awk to perform this substitution. However, I would like to avoid the word "class" in comments or elsewhere from being replaced. Can anyone think of a solution for this?

+1  A: 

How standard is the formatting of your code? For instance, could you look for 'class' in a line that ends with { or where the next line begins with { or some such?

Amber
I was thinking of that, but the code has been written over 3 years by several different people. While the formatting is generally consistent, there are sections of the code that are formatted completely differently. (brace on same line as opposed to next line, etc.)
Chinmay Kanchi
I suppose running it through a code formatter would be one option, but that depends on how much you trust the formatter not to break the actual functionality of the code; I haven't had much experience with them in combination with extensive projects so I can't personally give an opinion on that option.
Amber
+1  A: 

No way to be certain to get this 100% right without a java parser. But, the following may be close enough:

sed -i.bak 's/\\(public\\|private\\|protected\\)\\(.*\\)class/\\1 strictfp \\2 class/g' $file

I think I got the escapes right, but I'm writing this from a windows machine and haven't tested it.

The above will trip up if you have comments with 'public/private/protected' followed by 'class'.

What, you don't have Cygwin? Seriously, get it :-)
paxdiablo
The only issue I could see with that is that the public/private/protected keyword isn't required; without one of the three the class just defaults to package-private.
Amber
This will skip classes with package access level (i.e. no access keyword), and will match something like "publicclass".
Pavel Minaev
Oh, and it would also match something like `public void foo() { ... A.class ... }`
Pavel Minaev
It would also miss abstract classes etc., but it's a good starting point. Thanks
Chinmay Kanchi
+1  A: 

As a complete catch-all, no, there's no RegEx for that. You'd essentially need to write a Java interpreter (or at least a parser) in order to account for any theoretical construction of a class. That being said, you really should be safe if the word class is the first non-whitespace bit on the line, or if it's preceded by an access modifier that is the first non-whitespace bit on the line.

Adam Robinson
+1  A: 

I can think of two possibilities:

  • Use a parser rather than a regular expression (REs aren't meant for everything). A parser will far better understand the language syntax.
  • Make your code base consistent so that you will not pick up errant "class" strings.

Neither of these are very satisfactory. The first is actually quite hard to write, the second hard to get right.

My advice would be to just find an RE and turn it loose on a local copy of the source code, then examine all the changes. Whatever changes that were made in error, tweak the RE and try again.

Then introduce coding standards and gradually change all the non-conforming definitions to be correct.

paxdiablo
+2  A: 

For such a task, I would first recommend writing a small program that verifies all the *.class files in a directory tree actually have (or do not have) the correct strictfp setting. Then, whatever you choose to do to solve the source code modification problem, you can run the checker after the compiler to make sure that you've done the right thing.

This is actually just TDD applied to your particular problem.

Greg Hewgill
+1 Given that missing out the strictfp may cause inconsistent results this is a really good idea
djna
That is a good idea. I assume you mean using the reflection API to examine the classes? Or were you thinking of something else?
Chinmay Kanchi
I actually had something like BCEL in mind: http://jakarta.apache.org/bcel/ You can load and inspect the `.class` files directly without having to bother with reflection (and I don't think the reflection API even exposes the `strictfp` setting).
Greg Hewgill
+1  A: 

Since you want to switch back and forth between strictfp and no strictfp, it may be a better idea to modify the .class files as part of the build process. Then you can make this choice a build option and switch it without constantly changing source files.

starblue
Care to explain this further? I wasn't aware that there was a trivial way of modifying class files. There is unfortunately (and maddeningly) no way to specify strictfp as either a compile-time or a runtime option for all classes.
Chinmay Kanchi
I've not tried it, but some library for manipulating class files, for example BCEL, should be able to do it.
starblue
A: 

Starblue: Thanks! From looking up BCEL, I found JMangler, which is perfect, since I can modify existing .class files to add the strictfp modifier. http://javalab.cs.uni-bonn.de/research/jmangler/tutorial/using.html

Chinmay Kanchi
A: 

Just to let people know, I decided to go with Javassist in the end instead of BCEL, since Javassist seems to be a lot simpler to use and is perfectly adequate for my purposes. http://csg.is.titech.ac.jp/~chiba/javassist . In case anyone is curious, the code would go something like this:


    import javassist.*;
    ClassPool cp = new ClassPool(); 
    CtClass someClass = cp.get("SomeClass"); 
    someClass.setModifiers(Modifier.STRICT);
Chinmay Kanchi