How to list all deprecated classes to a file? - java

I'm aware that Intellij can scan for this - and there seems to be an ancient project called Scannotation. Neither of these seems to do what I want.
I want to list the full package names of classes in my codebase that are marked #Deprecated.
My question is: How to list all deprecated classes to a file?

You can use Structural Search.
CTRL + SHIFT + A --> Search Structurally
Use this to find all deprecated classes:
#Deprecated
class $class$ {
}

On a unix/linux system you could use find . -name *.java -regex "#Deprecated"
This would give a list of files with absolute paths that could be changed to package notation with sed or any other text editor.
On Windows you might consider installing git which brings a bash where you can run this command.

This is what you can use:
package util;
import io.github.lukehutch.fastclasspathscanner.FastClasspathScanner;
import io.github.lukehutch.fastclasspathscanner.matchprocessor.ClassAnnotationMatchProcessor;
public class AnnotationScanTest {
public static void main(String args[]) throws ClassNotFoundException {
new FastClasspathScanner("com")
// Optional, in case you want to debug any issues with scanning.
// Add this right after the constructor to maximize the amount of log info.
.verbose()
// Add a MatchProcessor ("Mechanism 1")
.matchClassesWithAnnotation(Deprecated.class, new ClassAnnotationMatchProcessor() {
#Override
public void processMatch(Class<?> matchingClass) {
System.out.println("Matching annotation: " + matchingClass);
}
})
// Actually perform the scan (nothing will happen without this call)
.scan();
}
}

Related

Eclipse autocompletion for jdk.* packages does not work

I write here because I noticed a strange behaviour of Eclipse IDE (2022-12).
Basically, the autocompletition does not work properly when I use a class from a jdk.* package.
For example:
import jdk.jshell.*;
public class Test {
private static final JShell JSHELL = JShell.create();
...
...
public static void main(String[] args) {}
}
Now when I write JSHELL. (e.g., inside the main method), I get only proposal for the methods of the Object class. No specific proposal is available.
What am I doing wrong?
Thanks.
Tried updating & reinstalling Eclipse.
jdk.* is filtered by default.
When you want to use something of jdk.* in a project, go to the preferences Java > Appearance > Type Filters and uncheck the item jdk.*.

Timing how long each file takes to compile with ant

Occasionally a slight modification to a Java source file like some additional explicit casts to help the compiler can improve compile time from 4 minutes to 3 seconds for a single java file (Especially in Java 8).
The problem is: In a large java project, how do you find which particular .java files are compiling slowly?
Is there a way to get Ant to time how long it takes to compile each individual .java file?
I think that this might be possible. Here's what I've found:
If you're using Java 8, you can register a Plugin with the compiler to add some additional functionality during compilation. The documentation has this to say about plugins:
It is expected that a typical plug-in will simply register a TaskListener to be informed of events during the execution of the compilation, and that the rest of the work will be done by the task listener.
So you can setup a plugin to use a TaskListener, and have the task listener log timestamps when class are being generated.
package xyz;
import com.sun.source.util.JavacTask;
import com.sun.source.util.Plugin;
public class TimestampPlugin implements Plugin {
#Override
public String getName() {
return "Timestamp_Plugin";
}
#Override
public void init(JavacTask task, String... strings) {
task.setTaskListener(new FileTimestampListener());
}
}
Documentation for TaskListener. A task listener is passed a TaskEvent, which has a Kind. In your case it sounds like you're interested in generation.
package xyz;
import com.sun.source.util.TaskEvent;
import com.sun.source.util.TaskListener;
import java.util.HashMap;
public class FileTimestampListener implements TaskListener {
HashMap<String, Long> timeStampMap = new HashMap<>();
#Override
public void started(TaskEvent taskEvent) {
if(TaskEvent.Kind.GENERATE.equals(taskEvent.getKind())) {
String name = taskEvent.getSourceFile().getName();
timeStampMap.put(name, System.currentTimeMillis());
}
}
#Override
public void finished(TaskEvent taskEvent) {
if(TaskEvent.Kind.GENERATE.equals(taskEvent.getKind())) {
String name = taskEvent.getSourceFile().getName();
System.out.println("Generated " + name + " over " + (System.currentTimeMillis() - timeStampMap.get(name)) + " milliseconds");
}
}
}
This is a simple example but it should be straightforward from here to set up something like a log file to store the information gathered. As you can see in the plugin's init function, arguments can be passed to the Plugin from the command line.
The plugin is configured by specifying it with the -Xplugin compiler argument. I'm not sure why but there doesn't appear to be any documentation on this page about it, but it can used by setting up a file called com.sun.source.util.Plugin (the FQ class name of the interface to implement) in your META-INF/services directory. So:
META-INF
|-- services
|-- com.sun.source.util.Plugin
And in that file list the FQ class name of your implementation of this class. So the file contents would be:
xyz.TimestampPlugin
In your Ant task you'll just need to specify a compiler flag -Xplugin:Timestamp_Plugin (note this is the name provided by the Plugin's getName() function). You'll also need to provide the compiled Plugin and runtime dependencies on the classpath, or the annotation processor path, if one is specified.

Java template for a project in Eclipse

Is it possible to make creation of (Java) file(s) in Eclipse easier/quicker.
I know there is that "Create new class wizard", but it is slow for my "special" needs...
I have a specific project in which I'm creating new classes often, but the structure for those classes is the same. Let say I want to create class A, so I want file A.java to be created as
class A {
public static void main(String[] args) {
}
static int solve() {
}
}
and it would be perfect that also ATest.java is created for this class, for example
class ATest {
#Test
int test1() {
Assert.assertEquals(0, A.solve());
}
}
or is there such plugin for Eclipse?
Yes, you can try using FastCode Plugin, where you can create new templates as per your requirement. As FastCode plugin supports custom templates, here is an example how to create the above class and test class together:
<template name="CREATE_NEW_CLASS">
<description>Used to Create class in the specified package.</description>
<allowed-file-names>*.*</allowed-file-names>
<first-template-item>package</first-template-item>
<second-template-item>none</second-template-item>
<additional-parameters>className</additional-parameters>
<template-body>
<![CDATA[
<fc:class type="class" name="${className}" package="${package.name}" project="${package.javaProject}">
public class ${className} {
public static void main(String[] args) {
}
static int solve() {
}
}
</fc:class>
<fc:class type="test" name="${className}Test" package="${package.name}" project="${package.javaProject}">
public class ${className}Test {
#Test
int test1(){
Assert.assertEquals(0, ${className}.solve());
}
}
</fc:class>
]]>
</template-body>
</template>
Once you add the template, you need to do import using import option in template preference page as explained in the document.
Yes, this is relatively simple to set up. Open the Project Properties and navigate to the Java Code Style > Code Templates section. Once there, check the box to enable project-specific settings. The generation template you want is under the Code part of the tree; you want Class Body. It is probably empty, but click the Edit... button to modify it.
Whatever you enter in the Edit dialog will be inserted between the class' brackets when using the New Class wizard.
There's no way I know of to automatically create another class (the Test in your case). But Eclipse has a JUnit wizard that makes doing so very easy. Just right-click on a class and choose New > Other... and then find Junit Test Case in the list. That wizard will guide you through creating the test class, including selecting the method(s) you want to test.
Note: these instructions set up the template for just the project or projects you select. You could also set up the same thing for your entire workspace Preferences, but doing so provides no way to share that configuration so that the same project checked out into another workspace will use it. I usually recommend making these kinds of settings on a per-project basis.
I'm not sure you need an IDE-specific template for that. When I was going through Project Euler, I had a setup like this:
public interface Problem {
public Object solve();
}
public class MyProblem implements Problem {
#Override
public Object solve() {
// do some stuff
return result;
}
}
Then in your (JUnit?) tests, you could use
Assert.assertEquals(expected, myProblemInstance.solve());
You can see my implementation here
If you do use an IDE template, you won't be able to use a generic solve() method, since it is not guaranteed that that class has that method. I would highly recommend using interfaces.

Why isn't my ResourceBundleControlProvider being loaded?

I thought I would use the new ResourceBundleControlProvider framework in Java 8 to fix something which Oracle themselves will never fix - the default encoding used when reading resource bundles.
So I made a control:
package com.acme.resources;
import java.io.IOException;
import java.util.Locale;
import java.util.ResourceBundle;
public class AcmeResourceBundleControl extends ResourceBundle.Control
{
#Override
public ResourceBundle newBundle(String baseName, Locale locale, String format,
ClassLoader loader, boolean reload)
throws IllegalAccessException, InstantiationException, IOException
{
throw new UnsupportedOperationException("TODO");
}
}
Then I made a provider:
package com.acme.resources;
import java.util.ResourceBundle;
import java.util.spi.ResourceBundleControlProvider;
public class AcmeResourceBundleControlProvider implements ResourceBundleControlProvider
{
private static final ResourceBundle.Control CONTROL = new AcmeResourceBundleControl();
#Override
public ResourceBundle.Control getControl(String baseName)
{
if (baseName.startsWith("com.acme."))
{
return CONTROL;
}
else
{
return null;
}
}
}
Then in META-INF/services/java.util.spi.ResourceBundleControlProvider:
com.acme.resources.AcmeResourceBundleControlProvider
Then I just tried to run our application from IDEA and I find that it never loads my provider (otherwise the exception would be raised.)
I have checked the names and they all seem to match up. I have checked the compiler output directory IDEA is using and it does contain the service file. I wrote a simple test program which just tries to look up the service:
public static void main(String[] args)
{
for (ResourceBundleControlProvider provider :
ServiceLoader.load(ResourceBundleControlProvider.class))
{
System.out.println(provider.getClass());
}
}
This does print out one entry which is the name of my implementation class. So the issue is not in the service file.
If I breakpoint inside ResourceBundle, I seem to be able to access the custom provider class. Initial forays into the debugger show that ServiceLoader isn't finding any implementations, but I can't figure out why. I'm sure there is some dodgy class loader magic going on which results in not loading my class. :(
Some scary documentation on the Javadoc makes it sound like it might have to be installed as a global extension. If that really is the case, it's a bit of a shame, because it seemed like a useful way to override the default (and in my opinion broken) behaviour. But I also read the tutorial on the matter and it didn't seem to be describing anything like that (unless the good behaviour was pulled out of Java 8 at the very last minute and the docs are out of date!)
The tutorial does state that the JAR containing the ResourceBundleControlProvider must be in the JVM's system extension directory. Section 6 of the tutorial describes the requirement:
java -Djava.ext.dirs=lib -cp build RBCPTest
When you install a Java extension, you typically put the JAR file of the extension in the lib/ext directory of your JRE. However, this command specifies the directory that contains Java extensions with the system property java.ext.dirs.
The JavaDoc for ServiceLoader.loadInstalled() also states that providers on the application's class path are ignored.
Your problem is that the java.util.ResourceBundle that comes with the JVM does a ServiceLoader.loadInstalled(ResourceBundleControlProvider.class) to obtain a list of providers in the static initializer, and uses the thus obtained list ever after.

How to run Java .class file from another .class file? (java newb)

I've been running different individual Java .java files in the Netbeans IDE by right-clicking the .java files themselves in the Project Explorer of Netbeans (the portion normally at the upper left part of Netbeans).
However, i've been googling on how to make a class file run another class file using code, but to no avail.
I have a project named "loadanotherfile" with 2 files, namely: Loadanotherfile.java and otherfile.java
I'm trying to make Loadanotherfile.java run otherfile.java, but I'm not exactly sure how. I read about Classloaders and URLClassloaders however these methods don't seem suitable for my purpose of running another .java file.
Below is the code of the 2 files i mentioned.
Loadanotherfile.java
package loadanotherfile;
public class Loadanotherfile {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
System.out.println("Hello World!");
// TODO code application logic here
}
}
otherfile.java
package loadanotherfile;
public class otherfile {
public static void main(String args[])
{
System.out.println("This is the other file.");
}
}
I have a feeling that the task has something to do with using the "import" syntax (namely something like import loadanotherfile.* but even if my guess is correct, I'm still not sure on how to make my Loadanotherfile.java run otherfile.java using code.
How can I load otherfile.java using Loadanothefile.java?
Cheers
In Loadanotherfile.java
otherfile.main(args);
Compile the two together, and then from Loadanotherfile,
otherfile.main(args);
will do the trick. You don't need to import since you're in the same package. Note the linked tutorial.
I would investigate (however) class instantiation, and creating an instance of a new class to invoke upon. Invoking static methods from static methods isn't very OO.
Try This:
className.main(Args){
}
This works! ive tested it myself.
Check the public void main line. If there IOException and not there then insert
in Loadanotherfile.java
use this
otherfile.main(args);{
}

Categories

Resources