How to enumerate all java classes in a directory in jython - jython

I find it tedious to import a java class in jython because of the long package names. e.g. com.example.x.y.z.SomeClass. It's a lot of typing. I want to import by using only the simple name of the class (SomeClass in my example). Is there a way of achieving it? Current solution in my head is to enumerate all the classes in the classpath and prepare a map of simple class name to the complete package name like -
SomeClass -> com.example.x.y.z.SomeClass
SomeOtherClass -> com.example.p.q.r.SomeOtherClass
etc. Then call a function something like below-
def intelligent_import(simple_class_name):
#No error checking, simplified for clarity
package_name = dict[simle_class_name]
simple_class_name = __import__(package_name)
for each of the classes. The only problem is that I don't know a method to enumearte all classes in a directory. Is there's a better way to do this? If not a method to enumerate all java classes in a directory will do.

This is a bit of a hack, I'm sure there's better our there, but if everything else fails, remember that JAR files are just ZIPs, and that each class will have a .class file in the jar.
However, rather than hacking the import mechanism like this, I'd rather just use an IDE with proper autocompletion (i.e. Eclipse/PyDev, it's the only one that can do it reliably in my experience), and rock the ctrl-space.

Related

How does import find the file path in Kotlin?

I've read the Kotlin doc (https://kotlinlang.org/docs/packages.html), and I understood that, when importing a package, the package name does not need to match the folder's path that stores the package (unlike what happens in Java).
I don't have issues creating a package and importing it into other classes.
What I'd like to understand, is how the compiler can find the file to import?
For example:
if a file import animals.mammals.cats.* :
import animals.mammals.cats.*
...
the entities to import do not need to be stored in the file /animals/mammals/cats.kt, as long as the package name is "animals.mammals.cats":
package animals.mammals.cats
...
This Kotlin file could be stored in src/animals/kittens for example.
In other words, how import can locate the file/s to load since the package name does not help?
Thanks!
TL;DR: the compiler is given the paths to all files to compile and to all dependencies, and therefore knows about all available packages and the declarations they contain.
First, note that the import statement itself is not really the most important. It's just a convenient syntax to avoid having to specify the package everywhere throughout the file. But technically you don't need to import anything to be able to use declarations from outside the current file - you can just use their fully qualified name (a.k.a FQN) which is the package name + . + the name of the declaration.
Now, on to your question. When you run the compiler, you provide the paths to the complete set of files to be compiled at the same time: you compile a module, not a single file. Therefore, it has access to all declarations in all those files and maintains its own data structures about the available classes and top-level functions, and all symbols in general. So it can store and find declarations using just their FQN. (DISCLAIMER: I'm no expert and I don't actually know how it's done internally, but I'm just guessing that conceptually it's like storing a big mapping between FQN and the information about the corresponding declaration.)
If the declaration you use is not in the set of files being compiled, it must be in one of your dependencies. You can tell the compiler about the available dependencies by specifying the list of jars containing their already compiled classes. This list of all classes available at compile time is called the compile classpath. This is why the tool you use to build your project (for instance, Gradle or your IDE) needs to know about those dependencies, so it can put their declarations on the compile classpath when calling the compiler for you. Then, just like declarations that are being compiled, the ones from the compile classpath can be easily looked up by the compiler (the path has been given to the compiler as an argument).
Now, when you actually run your compiled program, at least on the JVM, the classes required must be placed on the runtime classpath - a set of classes given to the java program. Finding those declarations while the program runs is done by classloaders. There are multiple classloaders, organized in a hierarchy, but there is no need to go into details here. Basically, each time a class is used for the first time while your program is running, one classloader will be asked to load that class into memory. There are different implementations of classloaders, but one of the most common is the URLClassLoader which is given the URLs of some jars that contain classes, and knows how to read classes from these jars into memory on-demand.

Is it possible to ignore classes from being instrumented based off of package folder?

We currently have ByteBuddy injecting some code into every method of a particular package, for example, com.contoso.widgets. This is working great!
However, we also have tests in the tst folder for the same package, for which we do not want to have ByteBuddy instrument on (but we do want the entities under test -- in the same package -- to be instrumented!).
Is there a way to define AgentBuilder so that it ignores all classes that come from tst, rather than src? It feels like I might be missing something obvious but haven't been successful after combing through the docs.
ByteBuddy works on byte code level, not on file system level. Have you tried to exclude tests by class name, e.g.
.type(not(nameEndsWith("Test").or(nameEndsWith("IT"))))
Or maybe you want to try something like excluding all classes containing methods annotated by #Test - untested, but maybe similar to this:
.type((typeDescription, classLoader, module, classBeingRedefined, protectionDomain) ->
typeDescription
.getDeclaredMethods()
.filter(inDefinedShape -> inDefinedShape.getDeclaredAnnotations().isAnnotationPresent(Test.class))
.size() == 0
)
Byte Buddy supports a RawMatcher where any type's ProtectionDomain is supplied. A protection domain offers access to the types's CodeSource from which you can find the file system location of its class file.
Do however note that this value depends on class loader, OS, packaging format and deployment. It might work for a standardized test environment but can fail you if you derive from it. It's therefore recommended to rely on something more structured.

How to access top level functions referring to the file they're declared in?

If you have a file MyUtils.kt in app/utils/:
package app.utils
fun log(message: String) {
println(message)
}
And you want to access this log() function from another file App.kt at app/, you will do this:
package app
import app.utils.log
fun main() {
log("hey")
}
But I don't like how the log() function is imported from the /utils package and not from the MyUtils.kt file explicitly.
One alternative would be to declare MyUtils.kt with package app.utils.MyUtils but I don't think it's a good practice to declare files in packages that don't have a matching folder.
Is there a way around this?
Edit: declaring an object or class wouldn't be a good solution either because of memory issues.
TL;DR
You can't.
Long answer
You seem to have a misconception that a class or object somehow adds some memory issues to your application.
That's not the case.
In fact, if you're running on the JVM, your log function will compile to the following:
public final class UtilsKt {
public static final void log(#NotNull String message) {
Intrinsics.checkParameterIsNotNull(message, "message");
System.out.println(message);
}
}
You can hit Meta+Shift+A on IntelliJ, then do Show Kotlin bytecode if you don't believe me.
Also, you seem to believe it should be possible to refer to a file name explicitly in a Kotlin import. There isn't a way to do that. Files have almost no bearings on the Kotlin compiled-code (it's kind of an accident that the file name actually reflects on the generated Java class name, as shown above).
Packages in Kotlin are usually arranged to meet the directories they are in... but that's not mandatory, by the way. You can write classes in several packages under the same directory. This means that the file names and even directory names do not really affect Kotlin runtime types and imports.
If you are worried about not being able to quickly find out where your functions are declared, I suggest you use the Java convention of calling the files by the name of the class that live in it, and then wrap all functions into an object (there's absolutely no runtime costs associated with that).
package app.utils
object MyUtils {
fun log(message:String) => println(message)
}
File: app/utils/MyUtils.kt
But notice that with any decent IDE, navigating to the declaration of a function is trivial (Meta+B in IntelliJ, usually) regardless of in which file it is in, so this problem is not normally an issue when you work with an IDE.

In Groovy, if class is not called why instantiation exception?

When I execute the following experimental code subset at http://groovyconsole.appspot.com/
class FileHandler {
def rootDir
FileHandler(String batchName) {
rootDir = '.\\Results\\'+batchName+'\\'
}
}
//def fileHandler = new FileHandler('Result-2012-12-15-10-48-55')
An exception results:
java.lang.NoSuchMethodException: FileHandler.<init>()
When I uncomment the last line that instantiates the class, the error goes away.
Can someone explain why this is? I'm basically attempting to segregate the definition and instantiation of the class into 2 files to be evaluated separately. Thanks
I'm not sure of the exact implementation details behind http://groovyconsole.appspot.com/ (source linked to from there points to Gaelyk, which I've not looked over). I'd bet it's looking for a no-arg constructor for the class you've presented, in an effort to find something runnable. (note that if you provide that, it still won't work, as it wants a main() :/)
Running locally in groovyConsole will die a bit sooner, with the following error message:
groovy.lang.GroovyRuntimeException: This script or class could not be run. It should either:
- have a main method,
- be a JUnit test or extend GroovyTestCase,
- implement the Runnable interface,
- or be compatible with a registered script runner.
This is perhaps more descriptive and to the point. If you want to run some Groovy as a simple script, you'll need to supply a jumping-in point. The easiest way is an executable statement in your groovy file, outside of any class definition (e.g, uncommenting your instantiation statement). Alternatively, a class with a main method should do it. (see here).
If 2 files is how you want to break it up, you can save the class file def in one groovy file (e.g., First.groovy) and create a second (e.g., Second.groovy) with just your executable statements. (I believe the first one will be in the classpath automatically when you run groovy Second, if both are in same directory)

How to find and remove unused class files from a project

My XCode project has grown somewhat, and I know that there are class files in there which are no longer being used. Is there an easy way to find all of these and remove them?
If the class files just sit in your project without being part of a target, just click on the project itself in the tree view, so you see all files in the table. Make sure you see the "Target" column in the table view, iterate through your targets and find the files that don't have a check anywhere -> they are no longer compiled.
But if you still compile the classes and they are no longer used, that case is a bit more difficult. Check out this project
http://www.karppinen.fi/analysistool/#dependency-graphs
You could create a dependency graph and try to find orphaned classes that way.
Edit: Link went dead, but there still seem to be projects of Objective-C dependency graphs around, for example https://github.com/nst/objc_dep
if they are C or C++ symbols, then you can just let the linker do the work for you.
if you're looking to remove objc symbols, then try to refactor the class name (e.g. to rename the class), and preview the dependencies that it turns up. if you reference classes/selectors/etc. by strings then... it may not be so effective. unfortunately, you often have to also test manually, to verify that removing a class does not break anything. remember that resources (like xibs) may reference/load objc classes as well.
This is a tricky question due to how dynamic objective-c is as you can never guarantee that a class is not going to be used.
Consider if you generate a class name and a selector at run time and then look up that class, instantiate that class and then call a method on that newly created object using that newly created selector. No where in your code do you explicitly name and instantiate that object but you are able to use it anyways. You could get that class name and selector name from anywhere outside of your code, even from some data from a server some where. How would you ever know which class is not going to be used? Because of this there are no tools that are able to perform what you are requesting.
Searching the project with the class name might be an option, thought it may not be the best solution. Specially it might be time consuming when you have many classes.