How to get an IType from a class name in Eclipse JDT - eclipse

I'm implementing a variant of the JUnit New Test Suite Wizard, and instead of getting test classes from the current project, I need to get them from another source. They come to me as strings of fully-qualified class names.
Some of them may not yet exist in this user's workspace, let alone in the classpath of the current project. The user will need to import the projects for these later, but I don't want to mess with that in my wizard yet. I need to just add all classes to the new suite whether they exist yet or not.
For those classes that are already in this project's classpath, I can use IJavaProject.findType(String fullyQualifiedName) . Is there an analogous way to get ITypes for classes that are not (yet) visible?
I would be happy to construct an IType out of thin air, but ITypes don't seem to like being constructed.

I don't think that is possible: the Java Document Model interfaces are created based on the classpath.
Even worse, if the project do not exist in the users workspace, the resulting code would not compile, and that is another reason for not allowing the arbitrary creation of such constructs.
If I were you, I would try to help the user to import the non-existing projects in case of types are not available, thus avoiding the tackling with the Java Document Model.

For my purposes, creating a HypotheticalType and a HypotheticalMethod got the job done. I'm attaching an overview in case anyone else needs to follow this path.
First I created a HypotheticalType and had it implement the IType interface. I instantiated one of these at the proper spot in my modified wizard. Using Eclipse's Outline view I created a method breakpoint on all methods in my new class. This let me detect which methods were actually getting called during execution of my wizard. I also modified the constructor to take, as a String, the name of the class I needed the wizard to handle.
Almost all of the new methods are ignored in this exercise. I found that I could keep the default implementation (return null or return false in most cases) for all methods except the following:
the constructor
exists() - no modification needed
getAncestor(int) - no modification needed, but it might be useful to return the package of my hypothetical class, e.g. if my class is java.lang.Object.class, return java.lang.
getDeclaringType() - no modification needed
getElementName() - modified to return the class name, e.g. if my class is java.lang.Object.class, return Object.
getElementType() - modified to return IJavaElement.TYPE
getFlags() - not modified yet, but might be
getMethod(String, String[]) - modified to return a new HypotheticalMethod(name)
getMethods() - modified to return new IMethod[] { new HypotheticalMethod("dudMethod") }
In the process I discovered that I need to be able to return a HypotheticalMethod, so I created that type as well, inheriting from IMethod, and used the same techniques to determine which methods had to be implemented. These are the only methods that get called while this wizard runs:
The constructor - add a String parameter to bring in the name of the method
exists() - no modification needed
isMainMethod() - no modification needed
That covers the solution to my original question. Zoltán, I'll be doing as you suggested in an upcoming iteration and trying to assist the user in both the case in which the desired class is not yet in this project's classpath, and the case in which the desired class is in some project not yet in the workspace.

Related

Any way to trigger creation of a list of all classes in a hierarchy in Swift 4?

Edit: So far it looks like the answer to my question is, "You can't do that in Swift." I currently have a solution whereby the subclass names are listed in an array and I loop around and instantiate them to trigger the process I'm describing below. If this is the best that can be done, I'll switch it to a plist so that least it's externally defined. Another option would be to scan a directory and load all files found, then I would just need to make sure the compiler output for certain classes is put into that directory...
I'm looking for a way to do something that I've done in C++ a few times. Essentially, I want to build a series of concrete classes that implement a particular protocol, and I want to those classes to automatically register themselves such that I can obtain a list of all such classes. It's a classic Prototype pattern (see GoF book) with a twist.
Here's my approach in C++; perhaps you can give me some ideas for how to do this in Swift 4? (This code is grossly simplified, but it should demonstrate the technique.)
class Base {
private:
static set<Base*> allClasses;
Base(Base &); // never defined
protected:
Base() {
allClasses.put(this);
}
public:
static set<Base*> getAllClasses();
virtual Base* clone() = 0;
};
As you can see, every time a subclass is instantiated, a pointer to the object will be added to the static Base::allClasses by the base class constructor.
This means every class inherited from Base can follow a simple pattern and it will be registered in Base::allClasses. My application can then retrieve the list of registered objects and manipulate them as required (clone new ones, call getter/setter methods, etc).
class Derived: public Base {
private:
static Derived global; // force default constructor call
Derived() {
// initialize the properties...
}
Derived(Derived &d) {
// whatever is needed for cloning...
}
public:
virtual Derived* clone() {
return new Derived(this);
}
};
My main application can retrieve the list of objects and use it to create new objects of classes that it knows nothing about. The base class could have a getName() method that the application uses to populate a menu; now the menu automatically updates when new subclasses are created with no code changes anywhere else in the application. This is a very powerful pattern in terms of producing extensible, loosely coupled code...
I want to do something similar in Swift. However, it looks like Swift is similar to Java, in that it has some kind of runtime loader and the subclasses in this scheme (such as Derived) are not loaded because they're never referenced. And if they're not loaded, then the global variable never triggers the constructor call and the object isn't registered with the base class. Breakpoints in the subclass constructor shows that it's not being invoked.
Is there a way to do the above? My goal is to be able to add a new subclass and have the application automatically pick up the fact that the class exists without me having to edit a plist file or doing anything other than writing the code and building the app.
Thanks for reading this far — I'm sure this is a bit of a tricky question to comprehend (I've had difficulty in the past explaining it!).
I'm answering my own question; maybe it'll help someone else.
My goal is to auto initialize subclasses such that they can register with a central authority and allow the application to retrieve a list of all such classes. As I put in my edited question, above, there doesn't appear to be a way to do this in Swift. I have confirmed this now.
I've tried a bunch of different techniques and nothing seems to work. My goal was to be able to add a .swift file with a class in it and rebuild, and have everything automagically know about the new class. I will be doing this a little differently, though.
I now plan to put all subclasses that need to be initialized this way into a particular directory in my application bundle, then my AppDelegate (or similar class) will be responsible for invoking a method that scans the directory using the filenames as the class names, and instantiating each one, thus building the list of "registered" subclasses.
When I have this working, I'll come back and post the code here (or in a GitHub project and link to it).
Same boat. So far the solution I've found is to list classes manually, but not as an array of strings (which is error-prone). An a array of classes such as this does the job:
class AClass {
class var subclasses: [AClass.Type] {
return [BClass.self, CClass.self, DClass.self]
}
}
As a bonus, this approach allows me to handle trees of classes, simply by overriding subclasses in each subclass.

How can I include a mxj Java jar/class folder in a freezed m4l-Device?

I have a maxforlive device using java/mxj.
I used all of these options to include my java files during development:
Including my (maven) target/classes directory through max.java.config.txt.
Adding a directory through Options > File Preferences
Adding a jar to the automatically generated (OSX) ~/Documents/Max 7/Max for Live Devices/MyProject Project/ directory
All of these paths work fine i.e. the files are picked up and my mxj object works.
However, when i freeze the device for publication, java files are not included from any of those paths.
I tried to make sense of
https://docs.cycling74.com/max7/tutorials/jitterchapter99_appendixd although I'm not building a standalone, but a freezed maxforlive device, so I included max.jar and mxj.mxo in the Project folder which did not work either.
When I copy my target/classes or target/classes/myproject folder into the generated Project folder (/code, /code/classes, /classes), max moves all the class files out into /code, creating a lot of work for me while not even picking the classes up for dev.
I saw devices on maxforlive.com with properly included java files, so I know it can be done. How can I achieve this?
Unfortunately this is a long standing bug in MFL.
Here is a movie from 2012 where I reproduce this, it has not been fixed since. http://arttech.nl/projectjavaissue.mov
This means that the only way to distribute MFL devices with java class files is to include them separately.
Ok, so here it is: Including just a single class with no other class dependencies except MaxObject works fine. There's also no need to add .java files like I said in my previous comment.
All you need to do is:
have the working mxj object in your patcher (doesn't matter where you saved it)
click the button on the bottom that says "Show containing project" on hover
add your classfile
freeze
When you have more classes, it gets complicated.
1) If you have your typical java hierarchy with folders and subfolders, that won't work. As you have to add each file separately, the hierarchy will be destroyed. Use a jar and add it to the containing project.
2) Here it comes, believe it or not: All the classes you are going to use will have to be loaded on first instantiation. I call it static class allocation ;)
A way to achieve that:
create a new instance of every class in the constructor of the class that extends MaxObject or any other constructors it calls. That includes classes with only static methods.
if you happen to use interfaces and create implementations of those dynamically (new Runnable() {...}), don't. Dynamic implementations are new classes.
Fun fact: you can override methods of classes, too. So go
class Runner {
public void run() { throw new Exception("not implemented"); }
}
then you can dynamically create a
new Runner() {
public void run() {
MaxObject.post("Even Mr. Gosling says interfaces were a mistake!");
}
}
Don't believe it? I don't blame ya. Look at
https://github.com/mihop/mxj-wsserver
and
http://www.maxforlive.com/library/device/3809
to be converted.

Eclipse 4 RCP - how to change what is showed in specific area?

I have splitted my application into two main areas.
Part(A)
PartStashContainer(B)
The content of A should be set based on what user wants.
So basically i can have 1..N classes which could be used in Class URI of Part in application model.
I don't know if i should replace the whole Part(A) with new dynamically created Part(C) which has content i want, or i should somehow to modify the existing Part (call setContributionURI, or setObject methods on Part object?).
It does make more sense to me to modify the existing Part, because it is defined in Application model and therefore already describing the location where the content should be.
Possible solutions:
Modify the Part object so it "reload" its content based on new setup (But how? Can setContributionURI or setObject methods help?)
Remove the old Part and add dynamically on same place in Application model the new Part (using EModelService and EPartService).
other solution??
If you want to reuse the Part then do something like:
MPart part = find or inject your part
MyClass myClass = (MyClass)part.getObject();
... call a method of MyClass to change the contents
MyClass is the class you specify for the object in the application model. You should add a method to that to let you change the contents.
Don't try to call setObject, this is really only for use by Eclipse. I don't think setContributionURI would do anything after the part is created (but I am not sure).
If you want to use different classes for the different data then you really should use different Parts.

Dont understand the concept of extends in URL.openConnection() in JAVA

Hi I am trying to learn JAVA deeply and so I am digging into the JDK source code in the following lines:
URL url = new URL("http://www.google.com");
URLConnection tmpConn = url.openConnection();
I attached the source code and set the breakpoint at the second line and stepped into the code. I can see the code flow is: URL.openConnection() -> sun.net.www.protocol.http.Handler.openConnection()
I have two questions about this
First In URL.openConnection() the code is:
public URLConnection openConnection() throws java.io.IOException {
return handler.openConnection(this);
}
handler is an object of URLStreamHandler, define as blow
transient URLStreamHandler handler;
But URLStreamHandler is a abstract class and method openConnection() is not implement in it so when handler calls this method, it should go to find a subclass who implement this method, right? But there are a lot classes who implement this methods in sun.net.www.protocol (like http.Hanlder, ftp.Handler ) How should the code know which "openConnection" method it should call? In this example, this handler.openConnection() will go into http.Handler and it is correct. (if I set the url as ftp://www.google.com, it will go into ftp.Handler) I cannot understand the mechanism.
second. I have attached the source code so I can step into the JDK and see the variables but for many classes like sun.net.www.protocol.http.Handler, there are not source code in src.zip. I googled this class and there is source code online I can get but why they did not put it (and many other classes) in the src.zip? Where can I find a comprehensive version of source code?
Thanks!
First the easy part:
... I googled this class and there is source code online I can get but why they did not put it (and many other classes) in the src.zip?
Two reasons:
In the old days when the Java code base was proprietary, this was treated as secret-ish ... and not included in the src.zip. When they relicensed Java 6 under the GPL, they didn't bother to change this. (Don't know why. Ask Oracle.)
Because any code in the sun.* tree is officially "an implementation detail subject to change without notice". If they provided the code directly, it helps customers to ignore that advice. That could lead to more friction / bad press when customer code breaks as a result on an unannounced change to sun.* code.
Where can I find a comprehensive version of source code?
You can find it in the OpenJDK 6 / 7 / 8 repositories and associated download bundles:
http://hg.openjdk.java.net/jdk6/jdk6 - http://download.java.net/openjdk/jdk6/
http://hg.openjdk.java.net/jdk7/jdk7 - http://download.java.net/openjdk/jdk7/
http://hg.openjdk.java.net/jdk8/jdk8
Now for the part about "learning Java deeply".
First, I think you are probably going about this learning in a "suboptimal" fashion. Rather than reading the Java class library, I think you should be reading books on java and design patterns and writing code for yourself.
To the specifics:
But URLStreamHandler is a abstract class and method openConnection() is not implement in it so when handler calls this method, it should go to find a subclass who implement this method, right?
At the point that the handler calls than method, it is calling it on an instance of the subclass. So finding the right method is handled by the JVM ... just like any other polymorphic dispatch.
The tricky part is how you got the instance of the sun.net.www.protocol.* handler class. And that happens something like this:
When a URL object is created, it calls getURLStreamHandler(protocol) to obtain a handler instance.
The code for this method looks to see if the handler instance for the protocol already exists and returns that if it does.
Otherwise, it sees if a protocol handler factory exists, and if it does it uses that to create the handler instance. (The protocol handler factory object can be set by an application.)
Otherwise, searches a configurable list of Java packages to find a class whose FQN is package + "." + protocol + "." + "Handler", loads it, and uses reflection to create an instance. (Configuration is via a System property.)
The reference to handler is stored in the URL's handler field, and the URL construction continues.
So, later on, when you call openConnection() on the URL object, the method uses the Handler instance that is specific to the protocol of the URL to create the connection object.
The purpose of this complicated process is to support URL connections for an open-ended set of protocols, to allow applications to provide handlers for new protocols, and to substitute their own handlers for existing protocols, both statically and dynamically. (And the code is more complicated than I've described above because it has to cope with multiple threads.)
This is making use of a number of design patterns (Caches, Adapters, Factory Objects, and so on) together with Java specific stuff such as the system properties and reflection. But if you haven't read about and understood those design patterns, etcetera, you are unlikely to recognize them, and as a result you are likely to find the code totally bamboozling. Hence my advice above: learn the basics first!!
Take a look at URL.java. openConnection uses the URLStreamHandler that was previously set in the URL object itself.
The constructor calls getURLStreamHandler, which generates a class name dynamically and loads, and the instantiates, the appropriate class with the class loader.
But URLStreamHandler is a abstract class and method openConnection()
is not implement in it so when handler calls this method, it should go
to find a subclass who implement this method, right?
It has to be declared or abstract or implemented in URLStreamHandler. If you then give an instance of a class that extends URLStreamHandler with type URLStreamHandler and call the openConnection() method, it will call the one you have overriden in the instance of the class that extends URLStreamHandler if any, if none it will try to call the one in URLStreamHandler if implemented and else it will probably throw an exception or something.

ScalaTest: Issues with Singleton Object re-initialization

I am testing a parser I have written in Scala using ScalaTest. The parser handles one file at a time and it has a singleton object like following:
class Parser{...}
object Resolver {...}
The test case I have written is somewhat like this
describe("Syntax:") {
val dir = new File("tests\\syntax");
val files = dir.listFiles.filter(
f => """.*\.chalice$""".r.findFirstIn(f.getName).isDefined);
for(inputFile <- files) {
val parser = new Parser();
val c = Resolver.getClass.getConstructor();
c.setAccessible(true);
c.newInstance();
val iserror = errortest(inputFile)
val result = invokeparser(parser,inputFile.getAbsolutePath) //local method
it(inputFile.getName + (if (iserror)" ERR" else " NOERR") ){
if (!iserror) result should be (ResolverSuccess())
else if(result.isInstanceOf[ResolverError]) assert(true)
}
}
}
Now at each iteration the side effects of previous iterations inside the singleton object Resolver are not cleaned up.
Is there any way to specify to scalatest module to re-initialize the singleton objects?
Update: Using Daniel's suggestion, I have updated the code, also added more details.
Update: Apparently it is the Parser which is doing something fishy. At subsequent calls it doesn't discard the previous AST. strange. since this is off topic, I would dig more and probably use a separate thread for the discussion, thanks all for answering
Final Update: The issue was with a singleton object other than Resolver, it was in some other file so I had somehow missed it. I was able to solve this using Daniel Spiewak's reply. It is dirty way to do things but its also the only thing, given my circumstances and also given the fact I am writing a test code, which is not going into production use.
According to the language spec, no, there is no way to recreate singleton objects. However, it is possible to reflectively invoke the constructor of a singleton, which overwrites the internal MODULE$ field which contains the actual singleton value:
object Test
Test.hashCode // => e.g. 779942019
val c = Test.getClass.getConstructor()
c.setAccessible(true)
c.newInstance()
Test.hashCode // => e.g. 1806030550
Now that I've shared the evil secret with you, let me caution you never, ever to do this. I would try very very hard to adjust the code, rather than playing sneaky tricks like this one. However, if things are as you say, and you really do have no other option, this is at least something.
ScalaTest has several ways to let you reinitialize things between tests. However, this particular question is tough to answer without knowing more. The main question would be, what does it take to reinitialize the singleton object? If the singleton object can't be reinitialized without instantiating a new singleton object, then you'd need to make sure each test loaded the singleton object anew, which would require using custom class loaders. I find it hard to believe someone would design something that way, though. Can you update your question with more details like that? I'll take a look again later and see if the extra details makes the answer more obvious.
ScalaTest has a runpath that loads classes anew for each run, but not a testpath. So you'll have to roll your own. The real problem here is that someone has designed this in a way that it is not easily tested. I would look at loading Resolver and Parser with a URLClassLoader inside each test. That way you'd get a new Resolver each test.
You'll need to take Parser & Resolver off of the classpath and off of the runpath. Put them into a directory of their own. Then create a URLClassLoader for each test that points to that directory. Then call findClass("Parser") on that class loader to get it. I'm assuming Parser refers to Resolver, and in that case the JVM will go back to the class loader that loaded Parser to get Resolver, which is your URLClassLoader. Do a newInstance on the Parser to get the instance. That should solve your problem, because you'll get a new Resolver singleton object for each test.
No answer, but I do have a simple example of where you might want to reset the singleton object in order to test the singleton construction in multiple, potential situations. Consider something stupid like the following code. You may want to write tests that validates that an exception is thrown when the environment isn't setup correctly and also write a test validates that an exception does not occur when the environment is not setup correctly. I know, I know everyone says, "Provide a default when the environment isn't setup correctly." but I DO NOT want to do this; it would cause issues because there would be no notification that you're using the wrong system.
object RequiredProperties extends Enumeration {
type RequiredProperties = String
private def getRequiredEnvProp(propName: String) = {
sys.env.get(propName) match {
case None => throw new RuntimeException(s"$propName is required but not found in the environment.")
case Some(x) => x
}
}
val ENVIRONMENT: String = getRequiredEnvProp("ENVIRONMENT")
}
Usage:
Init(RequiredProperties.ENVIRONMENT)
If I provided a default then the user would never know that it wasn't set and defaulted to the dev environment. Or something along these lines.