I'm aware of all the arguments against conditional compilation in Java. In this specific case, I'd only want to have a small IF in order to be able to test whether the code runs in Eclipse or not. The reason for this is that when I override a View to use my special processing, Eclipse in some cases cannot compile the modified View and display it in the IDE (there are many cases resulting in this behavior but a specific one is when the code refers to a JNI library that Eclipse, obviously, cannot execute).
Right now I'm using
if (!Build.DEVICE.startsWith("generic"))
// do something
and it works but I don't really like doing a string comparison every single time in an onDraw(), for instance. I'd need a simpler way, a cheaper condition to see if I'm in Eclipse and avoid some actions then.
Edit: To be clearer, I'm looking for a possible Java/Android/Eclipse equivalent of C#'s Component.DesignMode property.
The best I could come up with so far is:
import android.os.Build;
public class IDE {
private static IDE instance = null;
protected boolean designMode = false;
private IDE() {
designMode = Build.DEVICE.startsWith("generic");
}
public static IDE getInstance() {
if (instance == null)
instance = new IDE();
return instance;
}
public static boolean DesignMode() {
return getInstance().designMode;
}
}
This is a singleton class that encapsulates the check and can be queried as:
if (!IDE.DesignMode())
// do something
Related
I have implemented a Plugin mechanism and language packs using ResourceBundles in Java.
It works perfectly fine if I want to get a ResourceBundle from the core program (not from a plugin).
The problem is that I want to add the possibility to create a ResourceBundle that is in the plugin and only works within the plugin.
Plugins are loaded using URLClassLoaders and Reflections. I cannot access (I don't want to) plugin ClassLoaders from the translation class.
So, the program loads the plugin and executes a method inside the plugin later (The plugin is not in the Classpath) and that plugin executes the translate method.
In order to archieve this, I want to get the ClassLoader Object from the calling method.
Somethng like this or this might be useful, but I don't see a way to get the Class/ClassLoader and not the name of the class.
I thought that I could use the Stacktrace to get the ClassLoader of the calling method but I can only get the name using .getClassName and no Class or ClassLoader Object of the Caller.
This is what I have:
translate
public static String translate(Locale locale,String s) {
for (ResourceBundle bundle : getResourceBundles(locale/*,Thread.currentThread().getStackTrace()[1].getClassLoader();*/)) {
try {
return bundle.getString(s);
}catch (MissingResourceException e) {
//ignore/next iteration
}
}
return s;
}
getResourceBundles
private static Set<ResourceBundle> getResourceBundles(Locale locale,ClassLoader... loaders){
Set<ResourceBundle> bundles=new HashSet<>();
bundles.add(ResourceBundle.getBundle(BASE_NAME,locale,MyClass.class.getClassLoader()));
for (ClassLoader loader : loaders) {
ResourceBundle pluginBundle=getResourceBundle(g,loader);
if (pluginBundle!=null) {
bundles.add(pluginBundle);
}
}
return bundles;
}
I don’t think that this trial and error approach is a good idea. Neither is refetching all bundles for every single string. It doesn’t even seem that this translation service adds a value over the alternative of just letting the plugin read their bundle and call getString on it, at least not a value that justifies the overhead and complexity of the code.
Since the standard ResourceBundle.getBundle methods do already consider the caller’s context, the field declaration and acquisition expression would be a trivial single-liner when being placed within the plugin and invoking getString on it, is not more complicated than invoking your translation service’s method.
For completeness, getting the caller class in a standard way, is possible starting with Java 9. Then, you can do it like
private static final StackWalker STACK_WALKER
= StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
public static String translate(Locale locale, String s) {
for(ResourceBundle bundle: getResourceBundles(locale,
STACK_WALKER.getCallerClass().getClassLoader())) {
try {
return bundle.getString(s);
}catch (MissingResourceException e) {
//ignore/next iteration
}
}
return s;
}
I use ASM to update the class stack map, but when asm getMergedType, the following exception occurs:
java.lang.RuntimeException:
java.io.IOException: Resource not found for IntefaceImplA.
If without asm modify the class method, it does work fine.
I have defined two interfaces A and B: IntefaceImplA and
IntefaceImplB.
My environment source code:
IntefaceA.java
public interface IntefaceA {
void inteface();
}
IntefaceImplA.java
public class IntefaceImplA implements IntefaceA {
#Override
public void inteface() {
}
}
IntefaceImplB.java
public class IntefaceImplB implements IntefaceA {
#Override
public void inteface() {
}
}
Test.java
public class Test {
public IntefaceA getImpl(boolean b) {
IntefaceA a = b ? new IntefaceImplA() : new IntefaceImplB();
return a;
}
}
Main.java
public class Main {
public static void main(String args[]) {
....
if (a instance of Test) {
..
...
}
}
}
After I compiled a runner jar, and delete the IntefaceImplA.class and IntefaceA.class manually from the jar. why i wanna to delete those classes files, since the spring always like to do this stuff.
the runner jar can be run normal without ASM, but use Asm will occur exception. since the asm wanna to getMergedType for IntefaceImplA and IntefaceImplB, but IntefaceImplA was deleted by me.
After investigate the ASM ClassWriter source code i found below code:
protected String getCommonSuperClass(String type1, String type2)
{
ClassLoader classLoader = this.getClass().getClassLoader();
Class c;
Class d;
try {
c = Class.forName(type1.replace('/', '.'), false, classLoader);
d = Class.forName(type2.replace('/', '.'), false, classLoader);
} catch (Exception var7) {
throw new RuntimeException(var7.toString());
}
if(c.isAssignableFrom(d)) {
return type1;
} else if(d.isAssignableFrom(c)) {
return type2;
} else if(!c.isInterface() && !d.isInterface()) {
do {
c = c.getSuperclass();
} while(!c.isAssignableFrom(d));
return c.getName().replace('.', '/');
} else {
return "java/lang/Object";
}
}
Actually, I deleted the related class file, the classloader cannot find the class. but without asm the Program does work normal.
Should I enhance the override to the getCommonSuperClass method, if occur exception then return java/lang/Object for it? that's funny
Generally, overriding getCommonSuperClass to use a different strategy, e.g. without loading the class, is a valid use case. As it’s documentation states:
The default implementation of this method loads the two given classes and uses the java.lang.Class methods to find the common super class. It can be overridden to compute this common super type in other ways, in particular without actually loading any class, or to take into account the class that is currently being generated by this ClassWriter, which can of course not be loaded since it is under construction.
Besides the possibility that either or both arguments are classes you are currently constructing (or changing substantially), it might be the case that the context of the code transforming tool is not the context in which the classes will eventually run, so they don’t have to be accessible via Class.forName in that context. Since Class.forName uses the caller’s context, which is ASM’s ClassWriter, it is even possible that ASM can’t access the class despite it is available in the context of the code using ASM (if different class loaders are involved).
Another valid scenario is to have a more efficient way to resolve the request by using already available meta information without actually loading the class.
But, of course, it is not a valid resolution to just return "java/lang/Object". While this is indeed a common super type of every argument, it isn’t necessarily the right type for the code. To stay with your example,
public IntefaceA getImpl(boolean b) {
IntefaceA a = b ? new IntefaceImplA() : new IntefaceImplB();
return a;
}
the common super type of IntefaceImplA and IntefaceImplB is not only required to verify the validity of assigning either type to it, it is also the result type of the conditional expression, which must be assignable to the return type of the method. If you use java/lang/Object as common super type, a verifier will reject the code as it can’t be assignable to IntefaceA.
The original stackmap, very likely reporting IntefaceA as common super, will be accepted by the verifier as that type is identical to the method’s return type, so it can be considered assignable, even without loading the type. The test, whether either, IntefaceImplA and IntefaceImplB, is assignable to that specified common type, might be postponed to the point where these types are actually loaded and since you said, you deleted IntefaceA, this can never happen.
A method whose declared return type is absent, can’t work at all. The only explanation of your observation that “without asm the program does work normal”, is, that this method was never invoked at all during your test. You most probably created a time bomb in your software by deleting classes in use.
It’s not clear why you did this. Your explanation “since the spring always like to do this stuff” is far away from being comprehensible.
But you can use the overriding approach to get the same behavior as with the unmodified code. It just doesn’t work by return java/lang/Object. You could use
#Override
protected String getCommonSuperClass(String type1, String type2) {
if(type1.matches("IntefaceImpl[AB]") && type2.matches("IntefaceImpl[AB]"))
return "IntefaceA";
return super.getCommonSuperClass(type1, type2);
}
Of course, if you deleted more class files, you have to add more special cases.
An entirely different approach is not to use the COMPUTE_FRAMES option. This option implies that ASM will recompute all stack map frames from scratch, which is great for the lazy programmer, but implies a lot of unnecessary work if you are just doing little code transformations on an existing class and, of course, creates the requirement to have a working getCommonSuperClass method.
Without that option, the ClassWriter will just reproduce the frames the ClassReader reports, so all unchanged methods will also have unchanged stack maps. You will have to care about the methods whose code you change, but for a lot of typical code transformation tasks, you can still keep the original frames. E.g. if you just redirect method calls to signature-compatible targets or inject logging statements which leave the stack in the same state it was before them, you can still keep the original frames, which happens automatically. Note the existence of the ClassWriter(ClassReader,int) constructor, which allows an even more efficient transfer of the methods you don’t change.
Only if you change the branch structure or insert code with branches, you have to care for frames. But even then, it’s often worth learning how to do this, as the automatic calculation is quiet expensive while you usually have the necessary information already when doing a code transformation.
I am trying to test utility method which check if particular class is on class path, if yes return true else return false.
Why I am doing this: I have to independent classes extending same class, and only one of it will be on classpath. Need to do specific thing if one particular is on classpath.
Using kind of below method to check if particular class is on class path.
This check will be done only once after first request.
I'd checked Class.forName() also but decided to go with below approach.
My utility method looks something like this:
public static boolean isMyClassOnClassPath() {
try {
ClassLoader.getSystemClassLoader().loadClass("com.MyClass");
return true;
} catch (ClassNotFoundException ex) {
return false;
}
}
Checking false condition is easy as particular class is not not the ClassPath.
I'm trying to write Junit for positive scenario when this method will return true.
#Test
public void isMyClassOnClassPathShouldReturnTrueWhenMyClassIsOnClassPath() throws Exception{
PowerMockito.mockStatic(MyClass.class);
ClassLoader classLoader = PowerMockito.mock(ClassLoader.class);
PowerMockito.mockStatic(ClassLoader.class);
PowerMockito.when(ClassLoader.getSystemClassLoader()).thenReturn(classLoader);
//trying to mock classLoader.loadClass, below way is incorrect
//PowerMockito.when(classLoader.loadClass("com.MyClass")).thenReturn(Class<java.lang.Object.class>);
Assert.assertTrue(MyClassUtil.isMyClassOnClassPath());
}
So is it possible to mock classLoader.loadClass() method?
Honestly: don't even think about doing something like that.
In short, you are like a person sitting on a tree that starts cutting random limbs of the tree that person is sitting on. Meaning: this is a central part of the JVM. Assume your mocking would work: then every caller to that method would receive your mocked loader! So, when your test case itself wanted to load some classes, it would run into your mock!
And as almost usual, when people claim "I need to user Powermock for xyz" your real problem is a different one: you created untestable code. By making that static call there, you prevent yourself from testing your code!
For starters, you can have a look here to learn how to write testable code. But in case you are curious how you could fix your design:
class ClassPathChecker {
private final ClassLoader classLoader;
ClassPathChecker() { this(ClassLoader.getSystemClassLoader()); }
ClassPathChecker(ClassLoader classLoader) {
this.classLoader = this.classLoader);
}
boolean canClassBeLoaded(String className) {
try {
classLoader.loadClass ...
The above uses dependency injection to insert a mocked ClassLoader; which gives you full control over everything that is going on. Without using Powermock at all.
And out of curiosity: why do you restrict yourself to the System classloader? Wouldn't a simple call like Class.forName("yourclass") tell you the same?
I'm just getting started with Java, and I'm confused about how to unit test Java classes while still keeping everything isolated. Specifically, I'm wondering how I might test a method like createProgram in this example:
package com.example.app;
import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;
import com.example.data_models.Program;
public class ProgramCreator {
private PersistenceManagerFactory pm_factory;
public ProgramCreator(PersistenceManagerFactory pm_factory) {
this.pm_factory = pm_factory;
}
public void createProgram(String name, String instructor, double price) {
PersistenceManager pm = getPersistenceManager();
try {
pm.makePersistent(new Program(name, instructor, price));
} finally {
pm.close();
}
}
private PersistenceManager getPersistenceManager()
{
return this.pm_factory.getPersistenceManager();
}
}
I'm pretty sure I can mock out the persistence manager factory using a library like mockito and use that to test that the makePersistent method is getting called with the right arguments, but how do I check that the fields of the program data model are correct while still keeping everything isolated? I don't want to rely on the program object's getter methods, as that would result in my unit tests for ProgramCreator being reliant on the Program class being correct. What do I do in this situation? (With Ruby, I'd probably just stub out the new method of the Program class. Is something like that possible in Java?)
By creating an object (Program) in createProgram method you are creating tight coupling between the objects. Instead delegate the work of creation to a factory and you can mock the factory in your unit test. This would mean we would be testing only what createProgram method is doing and nothing else. Trying to unit test code could give us indications to re-design/re-factor the code.
public class ProgramCreator {
private PersistenceManagerFactory pm_factory;
private ProgramFactory p_factory;
public ProgramCreator(PersistenceManagerFactory pm_factory, ProgramFactory pFactory) {
this.pm_factory = pm_factory;
this.p_factory = pFactory;
}
public void createProgram(String name, String instructor, double price) {
PersistenceManager pm = getPersistenceManager();
try {
pm.makePersistent(p_Factory.createProgram(name, instructor, price));
} finally {
pm.close();
}
}
}
A unit in is not necessarily limited to a single class, it is the smallest set of classes that work together. So there is nothing wrong with using the getters from Program while testing ProgramCreator.
You don't have to test everything, everywhere.
Do as you say: mock the appropriate code to test createProgram and see if the results of that are as you expect them to be (aka: there has been a program persisted with the given fields).
You don't have to necessarily test that you actually create a new Program that has those fields. You could just as well test in a different method whether or not new Program(name, instructor, price) creates a new object with the right values.
The most important part about unit tests is this flow:
-> General idea
-> Logic performed
-> End situation reached
Your situation fills this in as
-> I want to test createProgram with variables X, Y and Z
-> ??
-> The database should return a program that has values X, Y and Z
All together you don't really care what happens in the second step, as long as the end result works. For this reason you can allow more general tests in your code that basically perform logic and check if the result of all that equals your desired output.
The obvious issue with this is ofcourse: in the case of an error, won't this mean I have to manually debug to find the issue? Yes, it does. That's why you should add many smaller tests (like testing the constructor) to help pinpoint the exact issue.
There certainly is nothing wrong with using getters and setters. In fact, you will most certainly need them. It's about testing workflow, not necessarily testing isolated methods.
Today I needed to ensure some code sections were guaranteed to be removed from production using just core Java (no AspectJ). After a bit of thought I realized I could do the following, other than being a complete abuse of the concept of contractual assertions can anyone suggest practical problems that could arise?
public class ProductionVerifier {
static boolean isTest;
static {
// This will set isTest to true if run with -ea, otherwise
// the following line will be removed and isTest will be false.
assert isTest=true;
}
public static final boolean TEST = isTest;
public static final void runOnlyIfInTest(Runnable runable) {
// javac will remove the following section if TEST == false
if (TEST) {
runable.run();
}
}
}
import static ProductionVerifier.*;
public class DemonstrationClass {
private static Runnable notForClient = new Runnable() {
public void run(){System.out.println("h4x0r");}
};
public static void main (String[] args) {
runOnlyIfInTest(notForClient);
}
}
My main initial concern was that the scope of the test code allowed it to be accessed from the production environment, but I think even if I wrapped each set of test statements in if (TEST) blocks there is probably some more fundamental issues with the pattern.
Edit: To conclude from the answer and linked question, there is a maintenance/design concern, which is that the enabling of assertions now changes the behavior of arbitrary bits of the system, and a technical issue, which is that the code in these statements is not actually removed from the class file as TEST is not a compile time constant. These issues could be solved by removing the assertions hack, although refactoring the code not to need ProductionVerifier would be preferable.
If someone at the data center - for whatever reasons - enables assertions, your production is going to execute test code happily in the production environment: For example, if an administrator enables assertions to analyze another application, but he just picked the wrong one in his console. Or it's only possible to enable them globally. This just happens.
And you cannot really blame him: The basic problem is really that the connection between "assertions" and "conditionally execute production or test code" is not obvious.