how to change a method signature dynamically in java any utiltiy - java

I wanted to refactor a method signature of a java class using utility classes E.g.:
Test.java
public class{
public void test(int a, int b) {
.....
....
}
}
In my entire project, I wanted to change the methods with the above signature to a different one like below:
public void test(String str) {
..
}
without opening all the files and rewriting them.
antlr is used to convert code written in one language to another language.
I wanted to do these kind of refactoring using java utility kind of class where i will provide my input class as argument and refactoring patters as another argument.i have explored using codemodel and eclipse AST but no luck.

In Eclipse put your blinking cursor onto the method and hit ctrl+shift+r. This allows you to rename methods, variables etc -- whatever you have selected in the entire project.
EDIT: I misread your question.
You need to "change method signature". Most IDEs have similar features e.g., IntelliJ -- Right Click -- Refactor - Change Signature. If you do not have an IDE then you will have to write a script or manually change all the calls.

if IDE provided refactoring is not option then I use Notepad++, it allows you to find and replace things without opening files, by selecting parent directory. I hope that will help you as well.

Related

Conditionally Remove Java Methods at Compile-Time

I am trying to achieve something similar to the C# preprocessor. I am aware that Java does NOT have the same preprocessor capabilities, and am aware that there are ways to achieve similar results using design patterns such as Factory. However, I am still interested in finding a solution to this question.
Currently, what I do is create a class that contains several static final boolean attributes, such as the following example:
public class Preprocessor
{
public static final boolean FULLACCESS = false;
}
I then use this in the following manner:
public ClassName getClassName()
{
if(Preprocessor.FULLACCESS)
{
return this;
}
else
{
return this.DeepCopy();
}
}
So far so good, this solves my problem (the example above is trivial, but I do use this in other instances where it is helpful). My question is, would there be a way to place the conditional around an entire method, so that the method itself would be unavailable given the correct "Preprocessor" variables? For example, I would like to be able to make a specific constructor available only for packages that are given "Full Access", as follows:
public ClassName()
{
// do things
}
if(FULLACCESS)
{
public ClassName(ClassName thing)
{
// copy contents from thing to the object being created
}
}
Again, I am aware of the limitations (or design decisions) of Java as a language, and am aware that in most circumstances this is unnecessary. As a matter of fact, I have considered simply creating these "extra" methods and placing the entire code of them within a conditional, while throwing an Exception if the conditional is not active, but that is a very crude solution that does not seem helpful to my programmers when I make these libraries available to them.
Thank you very much in advance for any help.
Edit:
To complement the question, the reason why I am attempting to do this is that by using exceptions as a solution, the IDE would display methods as "available" when they are actually not. However, again, it might just be a case of my being ignorant of Java.
The reasons for my wanting to do this are primarily so that I may have more than one public interface available, say, one restrictive where control is tighter within the methods, and one more permissive where direct alteration of attributes is allowed. However, I do also want to be able to actively remove portions of code from the .class, for instance, in a Product Line development approach where certain variants are not available.
Edit2.:
Furthermore, it is important to note that I will be generating the documentation conditionally as well. Therefore, each compiled version of the packages would have its own documentation, containing only that which is actually available.
Well, you can make it happen. A word of caution, though...
I can only think of one time when I thought this kind of approach was the best way, and it turned out I was wrong. The case of changing a class's public interface especially looks like a red flag to me. Throwing an exception when the access level isn't high enough to invoke the method might be more code-friendly.
But anyway, when I thought I wanted a preprocessor, what I did was to write one. I created a custom annotation to place on conditionally-available methods, grabbed a Java parser and wrote a little program that used the parser to find and remove methods that have the annotation. Then add that (conditionally) to the build process.
Because it turned out to be useless to me, I discarded mine; and I've never seen anyone else do it and publish it; so as far as I know you'd have to roll your own.
This answer is based partially on the comments you have left on the question and on Mark's answer.
I would suggest that you do this using Java interfaces which expose just the API that you desire. When you need a less restrictive API contract, extend an interface or create a separate implementation of an existing interface to get what you need.
public interface A
{
void f();
}
A above is your general API. Now you want to have some special extra methods to test A or to debug it or manipulate it or whatever...
public interface B extends A
{
void specialAccess();
}
Also, Java now supports default method implementations for interfaces which might be useful to you depending on how you implement your API. They take the following form...
public interface A
{
List getList();
// this is still only an interface, but you have a default impl. here
default void add(Object o)
{
getList().add(o);
}
}
You can read more about default methods on Oracle's page about it here.
In your API, your general distribution of it could include A and omit B entirely, and omit any implementations that offer the special access; then you can include B and special implementations for the special access version of the API you mentioned. This would allow plain old Java objects, nothing different to the code other than an extra interface and maybe an extra implementation of it. The custom part would just be in your packaging of the library. If you want to hand someone a "non-special" low-access version, hand them a jar that does not include B and does not include any possible BImplementation, possibly by having a separate build script.
I use Netbeans for my Java work, and I like to let it use the default build scripts that it auto generates. So if I were doing this and I were doing it in Netbeans, I would probably create two projects, one for base API and one for special-access API, and I would make the special-access one dependent on the base project. That would leave me with two jars instead of one, but I would be fine with that; if two jars bothered me enough I would go through the extra step mentioned above of making a build script for the special access version.
Some examples straight from Java
Swing has examples of this kind of pattern. Notice that GUI components have a void paint(Graphics g). A Graphics gives you a certain set of functionality. Generally, that g is actually a Graphics2D, so you can treat it as such if you so desire.
void paint(Graphics g)
{
Graphics2d g2d = Graphics2d.class.cast(g);
}
Another example is with Swing component models. If you use a JList or a JComboBox to display a list of objects in a GUI, you probably do not use the default model it comes with if you want to change that list over time. Instead, you create a new model with added functionality and inject it.
JList list = new JList();
DefaultListModel model = new DefaultListModel();
list.setModel(model);
Now your JList model has extra functionality that is not normally apparent, including the ability to add and remove items easily.
Not only is extra functionality added this way, but the original author of ListModel did not even need to know that this functionality could exist.
the only way in Java to reach that is to use preprocessor, for instance PostgresJDBC team uses java comment preprocessor for such manipulations, here is example from their Driver.java
//#if mvn.project.property.postgresql.jdbc.spec >= "JDBC4.1"
#Override
public java.util.logging.Logger getParentLogger() {
return PARENT_LOGGER;
}
//#endif
With Gradle you can manage your sources and I think that no preprocessor macros are no longer needed. Right now in src directory you have main/java with all sources but if you need specific methods in e.g. debug and release builds to do / or not specific things then create debug/java and release/java in src and put YourClass there. Note that by doing this you'll have to have YourClass in debug/java and release/java but not in main/java.

How do I declare a method from a Java API as deprecated for my local project?

I am attempting to add functionality to my class, CustomList, which extends JList. Now all of the current usages of CustomList call the non-overridden method setModel(Listmodel<E> lm) from JList. I am stuck on an older version of Java, Java 1.6, which does not allow me to directly override this method due to erasure problems. All of my research has brought me to the conclusion that I must rename this method and replace all the current usages with the newly named method.
What I would like to do is give some warning to other people working with CustomList that they need to call this method rather than JList.setModel(ListModel<E> lm). I am unsure of how to locally deprecate a native method for my project.
A simple example outlining my new method is shown below:
public class CustomList<E> extends JList {
private ArrayList list;
public void newSetModel (ListModel<E> lm){
super.setModel(lm);
list = new ArrayList<Boolean> (lm.getSize());
}
}
Please note that I cannot simply make JList generic in the extends to allow an override since I am stuck with Java 1.6
There is no sane way to do that in Java.
Ideally, you have a build / CI process, and in that you can use tools for Policy Enforcement. Look at Checkstyle & PMD, perhaps one of them will allow you to blacklist a specific method call.
Failing that, you can use a low-level technology like asm or aspectj to write your own check, but it won't be easy. Or you can go old school and write a test that parses source files and looks for the bad method call, but that's very error-prone.
I'd say your best bet is letting your other team members know. Do you guys do code reviews? You should.

Is there a way to call imagej macro (.ijm) from java (i.e. have macro stored as string and execute it using a java control of imagej)?

It is reversed problem to:
How can I call/execute a java program from an ImageJ macro?
Whenever I write imagej I refer to fiji.
Of course a trivial solution is to create a .ijm from java string and call imagej using a system call with .ijm as an argument, but I search for better solution. Alternatively .ijm instructions can be translated into java calls but it is not very convenient (when .jvm is enough for the job it is very convenient way to keep it in this format).
Why is it useful? It can be used e.g. to distribute a .ijm macro in obfuscated way - make it more difficult to the user to extract the macro. String containing instructions for .ijm can be decrypted only when correct password is provided, etc. Thank you for any suggestions!
Use the ij.IJ.runMacro(String) method.
Here is an example:
import ij.IJ;
import ij.plugin.PlugIn;
public class Run_Macro implements PlugIn {
#Override
public void run(final String arg) {
final String macro =
"run(\"Clown (14K)\");\n" +
"run(\"Make Binary\");\n";
IJ.runMacro(macro);
}
}
A word of warning about obfuscation, though: Java is notoriously easy to decompile.
Correct me if I am wrong but one could call IJ.runMacroFile to refer to a given macro text file in the macro folder.
public void My_Macro() {
IJ.runMacroFile("My_Macro.txt");
}
Yet I don't know if you can run macros outside of the macro folders, for example from within a .jar

Is there a way to replace class by another one in Intellij Idea?

Guys, here is my problem: I have some class which is used in many places in my project. And I must replace this class with another from jar provided. Is there any ways to refactor this? I suppose this is a simple problem, but I dont know how to solve it.
Its not about replacing source code - what I want is to replace all class usages by class from my library and be able to completely remove my own class. Imagine I have created my own StringUtils and have found out that there is a apache.common StringUtils library, and now I want to use it everywhere in my code. And the signatures of class methods are not a problem: they coincide.
?
There is this "migrate" function. Right click in whatever class -> Refactor -> Migrate.
It's a bit annoying that you have to create a new migrate set and you can't run it from scratch. But it does exactly what you need.
You pick class or package to migrate and tell it to which class or package it should change. Press run and all usages are rewritten. Then you're free to delete the old class because there will be no usages.
EDIT: In the newer versions it isn't in the context menu anymore. Just go to the menu on top - Refactor - Migrate (or simply pres shift twice and type migrate).
Cheers!
If you are using static methods (like your StringUtils example suggests), delegate to the new class in your previous implementation like
public static String myOldMethod(String argument) {
return MyNewClass.myNewMethod(argument);
}
then select Refactor->Inline and select "All invocations and remove the method" in the option dialog. In this way you can handle method name changes and argument order changes are well.
I found it to be easy to use delete and rename:
Temporarily delete TargetClass (delete without usages).
Rename SourceClass to TargetClass with usages.
Restore TargetClass from VCS or local history.
The simplest way is to write a method mapping what you would like to inline.
Say you have a method
enum MyStringUtils {
public static boolean containsAnyCase(String searchFor, String searchIn) {
// something
}
}
// calling code
boolean found = MyStringUtils.containsAnyCase(find, in);
You want to use StringUtils.containsIgnoreCase however the class name, method name and order arguments are different.
So you change the body of the method to call the desired method instead.
public static boolean containsAnyCase(String searchFor, String searchIn) {
return StringUtils.containsIgnoreCase(searchIn, searchFor);
}
Select the method and <Crtl> + <Alt> + N. This will offer to inline this method everywhere and deletes your method. Your caller now looks like
boolean found = StringUtils.containsIgnoreCase(in, find);
This will work even if the original class uses an import of the class, import static of the method or no import at all.
Although I am not an expert in IntelliJ I can tell you that generally in java the class loading is done sequentially. I mean the class loader is looking for classes sequentially, so if the same class presents in class path several times it will take the first version.
So, it depends on how are you running your application. If for example you are using command line like java -cp lib.jar;myapp.jar com.mycompany.Main and both lib.jar and myapp.jar contain the same class Util the lib.jar version will be used.
If you want to achieve the same effect when running from IDE try to check the project properties. Probably you can control the order of library jars relatively to your project's classes? If not, probably you can add jars to bootstrap classpath. In this case add your lib.jar to bootstrap classpath (just to work on your IDE).
Good luck.

In Class.forName got ClassNotFoundException when obfuscating in j2me

I am able to run the following example code
//main class
String a="Menu";
Object o = Class.forName("org.test."+a).newInstance();
//Menu class
public class Menu()
{
public Menu()
{
System.out.println("con called");
}
}
It runs fine, but when I obfuscate the code I get a no ClassNotFoundException.
I am using netbean 6.9.1 . In Additional obfusating setting i added -keepnames class org.test.Menu. But still not working. Any solution?
The trivial reason: The obfuscator changed the name of org.test.Menu to something else (package name changed and/or class name changed). And the obfuscator can't "refactor" the classes so that String based class names in other class files are changed too.
If this is the case, tell the obfuscator not to touch the org.test package (keep that name and don't obfuscate the name of the class(es) inside).
This is by design. Obfuscation changes the names of all of your public identifiers (including class names), and so if you're referring to any of them via strings (like with Class.forName, or other forms of reflection), and especially strings that you calculate ("org.test." + a) that will break.
If you need to demand-load Menu via Class.forName, then you cannot obfuscate the Menu class.
It's been a long time since I looked at obfuscators, but IIRC some may be able to rewrite some strings for you if you tag them in a particular way; check the docs on the one you're using to see if it can. But even then, it's unlikely they'd be able to rewrite something like "org.test." + a for you. You'd have to have the full name in a single string.
Obfuscation Changes the Tokens, Identifiers so your hard coded string ("org.test.Menu") for name wouldn't be found.
Obfuscation changes the names of classes and so the name of class Menu will be changed to something else.
When you obfuscate the code it changes class name by some a,b' and so on..

Categories