I ran into a very strange problem that I don't know if I'm even allowed to do.
Basically I have two functions witch should have the same name but get different parameter objects which have the same name.
This is because I want to write a plugin for the game Minecraft and this should be compatible with BungeeCord and Bukkit servers.
public static void sendMessage(org.bukkit.command.CommandSender p, String k, Object...i){
//fancy stuff
}
public static void sendMessage(net.md_5.bungee.api.CommandSender p, String k, Object...i){
//fancy stuff
}
If the plugin is loaded by a Bukkit server the plugin it doesn't know anything about net.md_5.bungee.api.CommandSender since this is a class of the BungeeCord server core and the same is for org.bukkit.command.CommandSender where it is used by Bukkit but not by BungeeCore.
I have no problem compiling the code with IntellIJ even dough I'm a bit sceptic because if decompiled it looks like this:
import org.bukkit.command.CommandSender;
public static void sendMessage(CommandSender p, String k, Object...i){
//fancy stuff
}
public static void sendMessage(net.md_5.bungee.api.CommandSender p, String k, Object...i){
//fancy stuff
}
My first question is: Can I even do this, or will this give exceptions since not all Classes are loaded, even dough it will never get accessed?
Now if the first question can be answered by Sure you can then why is there a compilation problem by compiling eigther a Bukkit or a BungeeCord plugin using this sendMessage( function?
Bukkit:
BungeeCord:
Because if this doesn't work I know for sure that you can at least work with Classes that aren't loaded if you put them into your codeblock since this code works just fine and isn't even throwing an exception when not loaded by a server that is using org.bukkit.craftbukkit.v1_13_R2.entity.CraftPlayer aldough it is in the imports:
import org.bukkit.entity.Player;
import org.bukkit.craftbukkit.v1_13_R2.entity.CraftPlayer;
public static int getPing(Player p) {
String version = getVersion(instance.getServer());
if (version.startsWith("v1_8")) {
return ((org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer)p).getHandle().playerConnection.player.ping;
} else if (version.startsWith("v1_9")) {
return ((org.bukkit.craftbukkit.v1_9_R2.entity.CraftPlayer)p).getHandle().playerConnection.player.ping;
} else if (version.startsWith("v1_10")) {
return ((org.bukkit.craftbukkit.v1_10_R1.entity.CraftPlayer)p).getHandle().playerConnection.player.ping;
} else if (version.startsWith("v1_11")) {
return ((org.bukkit.craftbukkit.v1_11_R1.entity.CraftPlayer)p).getHandle().playerConnection.player.ping;
} else if (version.startsWith("v1_12")) {
return ((org.bukkit.craftbukkit.v1_12_R1.entity.CraftPlayer)p).getHandle().playerConnection.player.ping;
} else {
return ((CraftPlayer)p).getHandle().playerConnection.player.ping;
}
}
So is this really a thing I simply cannot do or is this a problem of the compiler of IntellIJ and if so how can I fix it?
Well my attempt to your idea would be to call methods in sub classes. It might be an issue that the non found class is a parameter. When the class is accessed (just my speculations) the parameters are tried to load to determine which method to use.
So something like the following would be the output.
In the class you access have:
public static void sendMessage(Object player, String k, Object...i){
if(isBukkit())
MyBukkitUtils.sendMessage(player, k, i);
else
MyBungeeUtils.sendMessage(player, k, i);
}
MyBukkitUtils:
public static void sendMessage(Object player, String k, Object...i){
if(!(player instanceOf CommandSender))
return;
CommandSender p = (CommandSender) player;
//fancy stuff
}
Same for MyBungeeUtils just with the BunggeeCommandSender.
I don't know your code, but if you have to have everything seperated you can just code two plugins (one for spigot, one for bungee) and use a include a library in both were the common code is placed.
Related
I have a Java application (an interpreter written in antlr4 to be precise) with numerous options in the code I would like to be [power] user configurable. Something like a config.properties file. Most of them are Boolean flags, if set, do this, else do that.
Currently, I have one class per flag, and the classes are scattered through-out the code, mostly in the same package where the implementation needs it. And, you can say:
import my.package.DoThis;
if (DoThis.isSet()) {
doThis();
} else {
doThat();
}
where the code for DoThis is something like
package my.package;
public class DoThis {
private static Boolean doThis = true; // the default
public static Boolean isSet() { return doThis; }
public static void set() { doThis = true; }
public static void clear() { doThis = false; }
}
And, there is a centralized part of the code that main calls, that initializes these options.
public void setup() {
DoThis.set();
DoAnother.clear();
if (cmd.option.debug()) { DoThird.set(); } else { DoThird.clear(): }
}
But, as I said, I'd like to clean the code up and use a configuration file that I can keep in the resources or a power user can override. A properties file or maybe a json file would seem like the right user interface.
However, properties read strings, do I check for yes/no, true/false? to set the flag. Or is there something better to do?
Should I also make all the options part of one class and perhaps store them in a map? What will make adding configuration options easiest?
Most importantly, I'd like to follow some form of Java best practices for doing so. I don't want to be that person who can write FORTRAN in any language. I want the code to look like what other Java programmers would naturally write. I'm pretty certain what I have now is not it.
I am not aware of a universally-accepted "best" approach for this. My preference would be not to have a separate class per flag, but rather to rather to centralise all the flags within a single class called, say, Config. It's public API might be something like the following (assuming the flags are called x, y and z):
public class Config {
private boolean x;
private boolean y;
private boolean z;
void setX(boolean value) { x = value; }
boolean getX() { return x; }
void setY(boolean value) { y = value; }
boolean getY() { return y; }
void setZ(boolean value) { z = value; }
boolean getZ() { return z; }
}
If you don't want to have to pass an instance of Config as a parameter to lots of different operations/constructors in your application, then you could create a singleton instance of Config.
I don't think my suggestion above would be too controversial among programmers. What is more likely to attract controversy is opinions about the "best" way to initialise the Config object. Some people might suggest that the Spring Framework should be used to inject values obtained from an XML file. Some other people might suggest that your setup() operation should read values from a configuration file in whatever happens to be your favourite syntax (properties, JSON, XML or whatever) and possibly allowing command-line options to override values specified in the configuration file
I want to wrap a C++ library (PCL) in Java code using JNI, but I am having inconsistent results. I have first created a PointXYZ class for testing and it looks like this:
package pcl;
public class PointXYZ extends NativeObject {
PointXYZ() { }
#Override
public native void alloc(); // creates pointer + handle on the native side
#Override
public native void dispose(); // sets handle to 0 and deletes pointer
public native float getX();
// ...
}
I have generated the C header for this class using javah, compiled everything using CMake, tested it using its getters and setters and everything works perfectly.
static {
System.setProperty("java.library.path", System.getProperty("user.dir") + "/lib");
System.loadLibrary("pcl_java_common");
}
#Test
void attributeAccessTest() {
PointXYZ p = new PointXYZ();
p.alloc();
p.setX(3);
assertEquals(p.getX(), 3);
p.dispose();
// all is good
}
Now I have done the exact same steps for a PointXYZRGB class which inherits from PointXYZ and when I try to test that it throws java.lang.UnsatisfiedLinkError. Here is the class:
package pcl;
public class PointXYZRGB extends PointXYZ {
public PointXYZRGB() { }
#Override
public native void alloc();
#Override
public native void dispose();
public native short getR();
// ...
}
I have checked the generated .dll using Dependency Walker and the PointXYZRGB methods are all present. Anyone knows what the problem could be?
UPDATE: Here are the .dll functions as requested in the comment:
The problem was that System.setProperty("java.library.path", System.getProperty("user.dir") + "/lib"); does not actually make Java look for .dll files in the given path. It essentially does nothing. Then why do the tests work for PointXYZ? This is was my mistake of having put an older .dll into the project root folder, so it was essentially looking for methods in that.
I'm searching for a concept to forward an object to subobjects.
Example:
I would like to create log files for several main Objects, that include sub objects (imagine a REST server that would log every single connection by ID).
Creating one big log file is simple ( redirect System.out.println, I already encapsulated that)
Example code:
class SubElementA{
public SubElementA(){
Debugger.debug("I am called, too");
}
}
Application.java
package com.dev4ag;
class Application{
private ElementA elA;
private String prefix;
public Application(String name){
this.elA = new ElementA();
this.prefix = name;
}
public void countUp(){
Debugger.debug(this.prefix+": I will now count up");
this.elA.doSomeStuff();
}
}
ElementA.java
package com.dev4ag;
class ElementA{
private int counter;
private SubElementA subElementA;
public void doSomeStuff(){
counter++;
Debugger.debug("Counter is: "+counter);
}
//Constructor
public ElementA(){
subElementA = new SubElementA();
this.counter = 0;
};
}
SubElementA.java
package com.dev4ag;
class SubElementA{
public SubElementA(){
Debugger.debug("I am called, too");
}
}
Debugger.java
package com.dev4ag;
public class Debugger {
public static void debug(String output){
//Just imagine we would write to a file here ;)
System.out.println(output);
}
}
(it was more easy to write system.out.println than to create a file, just imagine, Debugger.debug would write to a file).
Now I am thinking about a solution to create one Debug output target for each App. I could definitely change debug to not being static and create a debug object within Application.
But is there any way to use this object in the sub classes without forwarding the debug object either through Constructor or setter function, which would mean to have to add an object for the debugger to each class?
What would be the most beautiful solution for that?
Note that this solution might decrease performance a lot and it is pretty dirty way, but some loggers include such data.
But you can use Thread.currentThread().getStackTrace() to get stacktrace like in error and get class and method from where your method was called.
If you are using java9+ then you should probably use StackWalker API instead, especially that it have nice filters and other useful features.
So then you could guess app by class/method names on the stack.
I have an interface which looks like the following
interface Evaluator {
boolean requiresP2();
EvalResult evaluate(Param1 p1, Param2 p2, Param3 p3);
// some more methods
}
This interface is implemented by several classes. The parameter p2 of the evaluate method is used by some and not used by others. The method requiresP2 basically returns a boolean telling whether the evaluate method uses p2 or not.
Now, this questions may appear a little weird out of context but believe me, it makes sense in our use case. Plus, it would require a lot of time to refactor all the code to eliminate the need for the requiresP2 method so I would appreciate if we discuss solutions other than a top-to-bottom refactoring of the codebase.
The problem is that the return value of method requiresP2 is based on how the evaluate method is implemented. Therefore everyone must ensure that they update the requiresP2 method when they change the evaluate method.
I am looking for ways so that this can be enforced by the compiler/unit-tests/linters rather than leaving it to the developer's memory.
EDIT: I am still exploring the applicability of mocking frameworks to this problem.
I thought that I could reflection in unit tests to inspect evaluate's body in the unit test to check if it refers to p2 or not and then making sure it matches with the value returned by requiresP2 method but it seems that it is not possible to inspect method body using reflection.
I am looking for suggestions on how to do this. Any input is appreciated.
There is another option you did not mention: a Static Code Analysis tool.
You can use the SonarQube + SonarLint combination in order to get your desired enforcement:
Use the SonarQube server in order to create a new static code analysis rule, which will be based on the interface you are using and your unique use case.
Then install SonarLint on your IDE/IDEs (Eclipse and IntelliJ are both supported), and connect it to the SonarQube server.
This way the static code analysis scan will detect improper usage of your interface and indicate this with a visual marking in the IDE, on the relevant code lines (which is actually linting your code).
You can use ASM to check whether the parameter is used.
To add it to your project using e.g. Apache Ivy, you would add this to ivy.xml:
<dependency org="org.ow2.asm" name="asm" rev="6.1.1" />
Or do the equivalent for Maven, Gradle, etc. Then you can check on the parameter by:
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.util.concurrent.atomic.AtomicBoolean;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
// . . .
public static boolean usesP2(Evaluator evaluator) {
AtomicBoolean usesP2 = new AtomicBoolean(false);
String internalName = evaluator.getClass().getName().replace('.', '/');
String classFileResource = "/" + internalName + ".class";
ClassVisitor visitor = new ClassVisitor(Opcodes.ASM6) {
#Override
public MethodVisitor visitMethod(int access, String name,
String desc, String signature, String[] exceptions) {
if ("evaluate".equals(name)) {
return new MethodVisitor(Opcodes.ASM6) {
#Override
public void visitVarInsn(final int insn, final int slot) {
if (slot == 2) usesP2.set(true);
}
};
}
return super.visitMethod(access, name, desc, signature, exceptions);
}
};
try (InputStream is = Evaluator.class.getResourceAsStream(classFileResource)) {
ClassReader reader = new ClassReader(is);
reader.accept(visitor, 0);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
return usesP2.get();
}
public static void assertCorrectlyDocumentsP2(Evaluator evaluator) {
boolean usesP2 = usesP2(evaluator);
if (usesP2 && !evaluator.requiresP2()) {
throw new AssertionError(evaluator.getClass().getName() +
" uses P2 without documenting it");
}
if (!usesP2 && evaluator.requiresP2()) {
throw new AssertionError(evaluator.getClass().getName() +
" says it uses P2 but does not");
}
}
Unit tests:
#Test
public void testFalsePositive() {
assertCorrectlyDocumentsP2(new FalsePositive());
}
#Test
public static void testFalseNegative() {
assertCorrectlyDocumentsP2(new FalseNegative());
}
(This supposes there are two bad Evaluators, FalsePositive and FalseNegative, one of which documents that it uses P2 but doesn't, and the other which doesn't document that it uses P2 even though it does, respectively.)
Note: In usesP2 we check for a variable instruction (an instruction which accesses a local variable) in slot 2 of the stack frame. The slots are numbered from 0, and the first one is this. P2 is in slots 2 only because Evaluator::evaluate is an instance method. If it were a static method, we would have to check if slot 1 were used in order to detect if parameter P2 were used. Caveat lector.
We have some legacy code with Groovy, and we want to remove Groovy from the application, so, we need to get the java source code generated after using the gmaven plug-in.
Basically, in other words I am dynamically generating new classes (using gmaven Groovy maven plug in) and I would like to be able to obtain the java source code of such generated classes.
I researched a little bit and can see that the only goals for this plug in are
<goal>generateStubs</goal>
<goal>compile</goal>
<goal>generateTestStubs</goal>
<goal>testCompile</goal>
I can't see any goal that allows you to obtain the fully implemented java source code, the stub code is not enough for us as we need the final implementation source code in order to get rid of Groovy.
I'm not very familiar with the gmaven plugin, but I assume it compiles the groovy code into byte code. In this case, you can use a byte code decompiler, there is a nice list here. In the past I've used JAD and it was quite nice. The best ones will also try to create meaningful variable names based on class names.
One warning though - Groovy objects are derived from GObject, not java.lang.Object, so you would probably need to keep the groovy jar until the groovy->java porting is done. Also, be prepared that it won't be a very easy to read java...
It may be out of your scope (1 year old) but I fought against the same problem and found a method to retrieve the algorithm (not the java source code) from the decompiled groovy classes.
You may want to take a look : http://michael.laffargue.fr/blog/2013/11/02/decompiling-groovy-made-classes/
The generated stubs will be useless for you. They are just what their names suggests: stubs.
The stubs are only useful when doing joint java/groovy compilation. That's because there are two compilers involved in a java/groovy mixed project.
Parse groovy
Create stubs
Compile java and stubs (using javac)
Continue groovy compilation (using groovyc)
The groovy code will be compiled using groovyc compiler and the result is byte code.
This is an example of a generated stub:
package maba.groovy;
import java.lang.*;
import java.io.*;
import java.net.*;
import java.util.*;
import groovy.lang.*;
import groovy.util.*;
#groovy.util.logging.Log4j() public class Order
extends java.lang.Object implements
groovy.lang.GroovyObject {
public groovy.lang.MetaClass getMetaClass() { return (groovy.lang.MetaClass)null;}
public void setMetaClass(groovy.lang.MetaClass mc) { }
public java.lang.Object invokeMethod(java.lang.String method, java.lang.Object arguments) { return null;}
public java.lang.Object getProperty(java.lang.String property) { return null;}
public void setProperty(java.lang.String property, java.lang.Object value) { }
public int getPrice() { return (int)0;}
public void setPrice(int value) { }
public int getQuantity() { return (int)0;}
public void setQuantity(int value) { }
#java.lang.Override() public java.lang.String toString() { return (java.lang.String)null;}
}
As you can see there is nothing useful. And you will still depend on some groovy libraries.
This question has been on the mailing-list some time ago [0]. To summarize: Groovy to Java is hard to achieve since there are language constructs and APIs (if you do want to totally remove the Groovy dependency) that are not available in Java.
Especially with the introduction of call-site caching and other performance optimizing techniques the generated Java code would look a lot like this (for the matter of simplicity I just threw some script into JD-GUI [1]):
public class script1351632333660 extends Script
{
public script1351632333660()
{
script1351632333660 this;
CallSite[] arrayOfCallSite = $getCallSiteArray();
}
public script1351632333660(Binding arg1)
{
Binding context;
CallSite[] arrayOfCallSite = $getCallSiteArray();
ScriptBytecodeAdapter.invokeMethodOnSuperN($get$$class$groovy$lang$Script(), this, "setBinding", new Object[] { context });
}
public Object run()
{
CallSite[] arrayOfCallSite = $getCallSiteArray(); Object items = ScriptBytecodeAdapter.createList(new Object[0]);
Object[] item = (Object[])ScriptBytecodeAdapter.castToType(ScriptBytecodeAdapter.createList(new Object[] { "Fluff", arrayOfCallSite[1].callConstructor($get$$class$java$util$Date()), (Integer)DefaultTypeTransformation.box(11235813) }), $get$array$$class$java$lang$Object());
arrayOfCallSite[2].call(items, item);
arrayOfCallSite[3].callCurrent(this, items);
ValueRecorder localValueRecorder = new ValueRecorder();
try
{
Object tmp102_101 = items; localValueRecorder.record(tmp102_101, 8);
Object tmp126_121 = arrayOfCallSite[4].call(tmp102_101, new script1351632333660._run_closure1(this)); localValueRecorder.record(tmp126_121, 14); if (DefaultTypeTransformation.booleanUnbox(tmp126_121)) localValueRecorder.clear(); else ScriptBytecodeAdapter.assertFailed(AssertionRenderer.render("assert items.findAll { it }", localValueRecorder), null); } finally {
localValueRecorder.clear(); throw finally; } return null; return null; }
static { __$swapInit();
Long localLong1 = (Long)DefaultTypeTransformation.box(0L);
__timeStamp__239_neverHappen1351632333665 = localLong1.longValue();
Long localLong2 = (Long)DefaultTypeTransformation.box(1351632333665L);
__timeStamp = localLong2.longValue(); }
class _run_closure1 extends Closure implements GeneratedClosure { public _run_closure1(Object _thisObject) { super(_thisObject); }
public Object doCall(Object it) { CallSite[] arrayOfCallSite = $getCallSiteArray(); return it; return null;
}
// ...
[0] http://groovy.329449.n5.nabble.com/Java-lt-gt-Groovy-converters-td337442.html
[1] http://java.decompiler.free.fr