How do I know if I am visiting an anonymous class in ASM? - anonymous-class

I have extended the ASM ClassVisitor and want to know if the visited class in an anonymous class.
Since I do have the class file I figured that if the class file name ended with $[1-9][0-9]*.class it would be an anonymous class. But currency characters are valid in class names so for example a class named MyClass$1 would match (classfile is named MyClass$1.class) even though it is not an anonymous class. I know most people would probably not name things like this but it is allowed.
So I thought about overriding the visitOuterClass method to see if it had an outer class that would eliminate outer classes with names ending in $# but still you could have an inner non anonymous class name ending with, for example, $1.
So is there some way in ASM to know that it is visiting an anonymous class? Or a better trick than mine?
# means any number (regexp: [1-9][0-9]*)

The relevant criteria is whether the class’ InnerClasses attribute declares the class to be an anonymous inner class. ASM report the contents by calling visitInnerClass for each entry of the attribute, if present.
So you can check it like
public class CheckForInnerClass extends ClassVisitor {
public static void main(String[] args) throws IOException {
Class<?>[] test={ Object.class, Map.Entry.class, new Object(){}.getClass() };
for(Class<?> c: test) {
new ClassReader(c.getName())
.accept(new CheckForInnerClass(Opcodes.ASM5), ClassReader.SKIP_CODE);
}
}
private String actualName;
private Boolean anonymous;
public CheckForInnerClass(int api) {
super(Opcodes.ASM5);
}
#Override
public void visit(int version, int access,
String name, String signature, String superName, String[] interfaces) {
actualName=name;
}
#Override
public void visitInnerClass(String name, String outer, String innerName, int access) {
if(name.equals(actualName)) {
anonymous = innerName==null;
}
}
#Override
public void visitEnd() {
System.out.println(actualName+": is "
+ (anonymous==null? "not an": anonymous? "an anonymous": "a named")
+ " inner class");
}
}
which prints
java/lang/Object: is not an inner class
java/util/Map$Entry: is a named inner class
CheckForInnerClass$1: is an anonymous inner class

Related

How can i extend spring-kafka's '#KafkaListener' annotation to create my own annotation with limited attributes?

I've been using '#KafkaListener' at method level to create consumers. Now, I'm trying to create my own custom annotation by extending '#KafkaListener' and limit the no of attributes (for example, because of some reasons, I don't want to expose attributes like 'errorHandler' 'containerGroup' etc ). Now my question is, to implement this, is there any option to extend the existing '#KafkaListener' ? Please suggest.
Yes, it's quite easy.
#SpringBootApplication
public class So61684460Application {
public static void main(String[] args) {
SpringApplication.run(So61684460Application.class, args);
}
#MyListener(topics = "so61684460", id = "so61684460")
public void listen(String in) {
System.out.println(in);
}
#Bean
public NewTopic topic() {
return TopicBuilder.name("so61684460").partitions(3).replicas(1).build();
}
}
#Retention(RetentionPolicy.RUNTIME)
#Target({ ElementType.TYPE, ElementType.METHOD, ElementType.ANNOTATION_TYPE })
#KafkaListener(concurrency = "${my.concurrency}")
#interface MyListener {
#AliasFor(annotation = KafkaListener.class, attribute = "id")
String id();
#AliasFor(annotation = KafkaListener.class, attribute = "topics")
String[] topics() default "";
}
As you can see, as well as restricting the visibility of some attributes, you can make them required (id above), change the default value, or set hard-coded or parameterized values in the invisible attributes (concurrency above).
This is described in the documentation.

Facing JDOMParseException : Content not allowed in prolog

org.jdom.input.JDOMParseException: Error on line 1 of document file:/home/omfys/Desktop/eclipse: Content is not allowed in prolog.
at org.jdom.input.SAXBuilder.build(SAXBuilder.java:501)
at org.jdom.input.SAXBuilder.build(SAXBuilder.java:847)
at org.jdom.input.SAXBuilder.build(SAXBuilder.java:826)
The first line of your document is probably incorrect.
View : Content is not allowed in Prolog SAXParserException
You probably have a class level attribute for the SAXBuilder ...
like this:
public class MyClass {
private static final SAXBuilder saxBuilder = new SAXBuilder();
public static Document myMethod(String argument) throws Exception {
... your functionality with the saxBuilder
}
}
(If this is the case) just declare and initialize the SAXBuilder within the method and it will be fixed ...

Resolve named registration dependency in Unity with runtime parameter

I have a following problem. I register my components and initialize them in Unity like this (example is for a Console application):
public class SharePointBootstrapper : UnityBootstrapper
{
...
public object Initialize(Type type, object parameter) =>
Container.Resolve(type,
new DependencyOverride<IClientContext>(Container.Resolve<IClientContext>(parameter.ToString())),
new DependencyOverride<ITenantRepository>(Container.Resolve<ITenantRepository>(parameter.ToString())));
public void RegisterComponents()
{
Container
.RegisterType<IClientContext, SharePointOnlineClientContext>(SharePointClientContext.Online.ToString())
.RegisterType<IClientContext, SharePointOnPremiseClientContext>(SharePointClientContext.OnPremise.ToString())
.RegisterType<ITenantRepository, DocumentDbTenantRepository>(SharePointClientContext.Online.ToString())
.RegisterType<ITenantRepository, JsonTenantRepository>(SharePointClientContext.OnPremise.ToString());
}
}
public enum SharePointClientContext
{
Online,
OnPremise
}
class Program
{
static void Main(string[] args)
{
...
bootstrap.RegisterComponents();
var bla = bootstrap.Initialize(typeof(ISharePointManager), SharePointClientContext.Online);
}
}
So, I register my components in MVC, WCF, Console etc. once with RegisterComponents() and initialize them with Initialize().
My question is, if I want to initialize specific named registration at runtime, from e.g. user input, can it be done otherwise as the code presented (with InjectionFactory or similar)?
This code works fine, but I'm not happy with its implementation. I have a feeling that it could be written in RegisterComponents() instead of Initialize() so that it accepts a parameter of some type, but I don't know how to do it.
Or, is maybe my whole concept wrong? If so, what would you suggest? I need to resolve named registration from a parameter that is only known at runtime, regardless of the technology (MVC, WCF, Console, ...).
Thanks!
Instead of doing different registrations, I would do different resolves.
Let's say that you need to inject IClientContext, but you want different implementations depending on a runtime parameter.
I wrote a similiar answer here. Instead of injecting IClientContext, you could inject IClientContextFactory, which would be responsible for returning the correct IClientContext. It's called Strategy Pattern.
public interface IClientContextFactory
{
string Context { get; } // Add context to the interface.
}
public class SharePointOnlineClientContext : IClientContextFactory
{
public string Context
{
get
{
return SharePointClientContext.Online.ToString();
}
}
}
// Factory for resolving IClientContext.
public class ClientContextFactory : IClientContextFactory
{
public IEnumerable<IClientContext> _clientContexts;
public Factory(IClientContext[] clientContexts)
{
_clientContexts = clientContexts;
}
public IClientContext GetClientContext(string parameter)
{
IClientContext clientContext = _clientContexts.FirstOrDefault(x => x.Context == parameter);
return clientContext;
}
}
Register them all, just as you did. But instead of injecting IClientContext you inject IClientContextFactor.
There also another solution where you use a Func-factory. Look at option 3, in this answer. One may argue that this is a wrapper for the service locator-pattern, but I'll leave that discussion for another time.
public class ClientContextFactory : IClientContextFactory
{
private readonly Func<string, IClientContext> _createFunc;
public Factory(Func<string, IClientContext> createFunc)
{
_createFunc = createFunc;
}
public IClientContext CreateClientContext(string writesTo)
{
return _createFunc(writesTo);
}
}
And use named registrations:
container.RegisterType<IClientContext, SharePointOnlineClientContext>(SharePointClientContext.Online.ToString());
container.RegisterType<IClientContext, SharePointOnPremiseClientContext>(SharePointClientContext.OnPremise.ToString());
container.RegisterType<IFactory, Factory>(
new ContainerControlledLifetimeManager(), // Or any other lifetimemanager.
new InjectionConstructor(
new Func<string, IClientContext>(
context => container.Resolve<IClientContext>(context));
Usage:
public class MyService
{
public MyService(IClientContextFactory clientContextFactory)
{
_clientContextFactory = clientContextFactory;
}
public void DoStuff();
{
var myContext = SharePointClientContext.Online.ToString();
IClientContextclientContext = _clientContextFactory.CreateClientContext(myContext);
}
}

handle duplicate values for Spring #RequestParam

I have a Spring 3.2 Controller with basic request mappings like
#RequestMapping("/action")
public String action(#RequestParam("param") String param) {
//do stuff...
return "view";
}
This controller handles links created by non-technical business users. Sometimes the users mess it up and create links with duplicate parameters, e.g.,
www.example.com/action?param=value&param=value
The parameter is an exact duplicate and probably a copy/paste error.
My problem is that Spring is concatenating these dupes together, so that the url above will give "value,value" for param, when I want only "value".
What is a good way to detect and handle these duplicates? I know I could change all my #RequestParams to List<String>s and go from there, but that's a whole lot of boilerplate over dozens of request mappings.
Ideally there would be a way to intercept and modify the url parameters before Spring attempts to bind them -- but only for this controller.
I found that I can register a custom String property editor to do this.
class DuplicateParameterReducingPropertyEditor extends PropertyEditorSupport {
Object value;
#Override
public void setValue(Object value) {
if (value instanceof String[]) {
String[] strings = (String[])value;
Set<String> unique = Sets.newHashSet(strings);
this.value = unique.toArray();
} else {
this.value = value;
}
}
#Override
public void setAsText(String text) throws IllegalArgumentException {
this.value = text;
}
#Override
public String getAsText() {
return value.toString();
}
#Override
public Object getValue() {
return value;
}
};
I added this to my controller:
#InitBinder
public void initBinder(WebDataBinder binder) {
PropertyEditor stringEditor = new DuplicateParameterReducingPropertyEditor();
binder.registerCustomEditor(String.class, stringEditor);
}
So whenever Spring encounters a #RequestParam-annotated String method argument, the PropertyEditor is invoked to transform the incoming data if needed. In the case of duplicate parameters, Spring passes a String[] of the values to the property editor setValue, which I can then manipulate.
This does have the results I am looking for. I'm not sure of all the implications of this, though, so I can't endorse it as good solution yet. Not having to alter any handler method signatures is a big plus though.
A good idea would be to extend AbstractNamedValueMethodArgumentResolver with your own strategy. Then the strategy could be used wherever you deem necessary.
This strategy only works for Spring 3.1+ which is not a problem for you since you are using Spring 3.2
I faced the same issue in Spring boot. Eventually I came up with this solution using converter, in case it helps anyone.
This method should be added as part of your WebMvcConfigurer class.
#Override
public void addFormatters(FormatterRegistry registry) {
// Duplicate query parameters converter
registry.addConverter(new Converter<String[], String>() {
public String convert(String[] arr) {
return arr[arr.length - 1]; // Return the last value
}
});
}

Java: How do I override a method of a class dynamically (class is eventually NOT in classpath)?

How do I call a method of a class dynamically + conditionally?
(Class is eventually not in classpath)
Let's say, I need the class NimbusLookAndFeel, but on some systems it's not available (i.e. OpenJDK-6).
So I must be able to:
Get to know it that class is available (at runtime),
If it's not the case, skip the whole thing.
How do I manage to override a method of a dynamically-loaded class
(thus creating an anonymous inner sub-class of it)?
Code example
public static void setNimbusUI(final IMethod<UIDefaults> method)
throws UnsupportedLookAndFeelException {
// NimbusLookAndFeel may be now available
UIManager.setLookAndFeel(new NimbusLookAndFeel() {
#Override
public UIDefaults getDefaults() {
UIDefaults ret = super.getDefaults();
method.perform(ret);
return ret;
}
});
}
EDIT:
Now I edited my code, as it was suggested, to intercept NoClassDefFoundError using try-catch. It fails. I don't know, if it's OpenJDK's fault. I get InvocationTargetException, caused by NoClassDefFoundError. Funny, that I can't catch InvocationTargetException: It's thrown anyway.
EDIT2::
Cause found: I was wrapping SwingUtilities.invokeAndWait(...) around the tested method, and that very invokeAndWait call throws NoClassDefFoundError when loading Nimbus fails.
EDIT3::
Can anyone please clarify where NoClassDefFoundError can occur at all? Because it seems that it's always the calling method, not the actual method which uses the non-existing class.
Get to know it that class is available (at runtime)
Put the usage in a try block ...
If it's not the case, skip the whole thing
... and leave the catch block empty (code smell?!).
How do I manage to override a method of a dynamically-loaded class
Just do it and make sure the compile-time dependency is satisfied. You are mixing things up here. Overriding takes place at compile time while class loading is a runtime thing.
For completeness, every class you write is dynamically loaded by the runtime environment when it is required.
So your code may look like:
public static void setNimbusUI(final IMethod<UIDefaults> method)
throws UnsupportedLookAndFeelException {
try {
// NimbusLookAndFeel may be now available
UIManager.setLookAndFeel(new NimbusLookAndFeel() {
#Override
public UIDefaults getDefaults() {
final UIDefaults defaults = super.getDefaults();
method.perform(defaults);
return defaults;
}
});
} catch (NoClassDefFoundError e) {
throw new UnsupportedLookAndFeelException(e);
}
}
Use BCEL to generate your dynamic subclass on the fly.
http://jakarta.apache.org/bcel/manual.html
The follow code should solve your problem. The Main class simulates your main class. Class A simulates the base class you want to extend (and you have no control of). Class B is the derived class of class A. Interface C simulates "function pointer" functionality that Java does not have. Let's see the code first...
The following is class A, the class you want to extend, but have no control of:
/* src/packageA/A.java */
package packageA;
public class A {
public A() {
}
public void doSomething(String s) {
System.out.println("This is from packageA.A: " + s);
}
}
The following is class B, the dummy derived class. Notice that, since it extends A, it must import packageA.A and class A must be available at the compile time of class B. A constructor with parameter C is essential, but implementing interface C is optional. If B implements C, you gain the convenience to call the method(s) on an instance of B directly (without reflection). In B.doSomething(), calling super.doSomething() is optional and depends on whether you want so, but calling c.doSomething() is essential (explained below):
/* src/packageB/B.java */
package packageB;
import packageA.A;
import packageC.C;
public class B extends A implements C {
private C c;
public B(C c) {
super();
this.c = c;
}
#Override
public void doSomething(String s) {
super.doSomething(s);
c.doSomething(s);
}
}
The following is the tricky interface C. Just put all the methods you want to override into this interface:
/* src/packageC/C.java */
package packageC;
public interface C {
public void doSomething(String s);
}
The following is the main class:
/* src/Main.java */
import packageC.C;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class Main {
public static void main(String[] args) {
doSomethingWithB("Hello");
}
public static void doSomethingWithB(final String t) {
Class classB = null;
try {
Class classA = Class.forName("packageA.A");
classB = Class.forName("packageB.B");
} catch (ClassNotFoundException e) {
System.out.println("packageA.A not found. Go without it!");
}
Constructor constructorB = null;
if (classB != null) {
try {
constructorB = classB.getConstructor(C.class);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
C objectB = null;
if (constructorB != null) {
try {
objectB = (C) constructorB.newInstance(new C() {
public void doSomething(String s) {
System.out.println("This is from anonymous inner class: " + t);
}
});
} catch (ClassCastException e) {
throw new RuntimeException(e);
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
}
if (objectB != null) {
objectB.doSomething("World");
}
}
}
Why does it compile and run?
You can see that in the Main class, only packageC.C is imported, and there is no reference to packageA.A or packageB.B. If there is any, the class loader will throw an exception on platforms that don't have packageA.A when it tries to load one of them.
How does it work?
In the first Class.forName(), it checks whether class A is available on the platform. If it is, ask the class loader to load class B, and store the resulting Class object in classB. Otherwise, ClassNotFoundException is thrown by Class.forName(), and the program goes without class A.
Then, if classB is not null, get the constructor of class B that accepts a single C object as parameter. Store the Constructor object in constructorB.
Then, if constructorB is not null, invoke constructorB.newInstance() to create a B object. Since there is a C object as parameter, you can create an anonymous class that implements interface C and pass the instance as the parameter value. This is just like what you do when you create an anonymous MouseListener.
(In fact, you don't have to separate the above try blocks. It is done so to make it clear what I am doing.)
If you made B implements C, you can cast the B object as a C reference at this time, and then you can call the overridden methods directly (without reflection).
What if class A does not have a "no parameter constructor"?
Just add the required parameters to class B, like public B(int extraParam, C c), and call super(extraParam) instead of super(). When creating the constructorB, also add the extra parameter, like classB.getConstructor(Integer.TYPE, C.class).
What happens to String s and String t?
t is used by the anonymous class directly. When objectB.doSomething("World"); is called, "World" is the s supplied to class B. Since super can't be used in the anonymous class (for obvious reasons), all the code that use super are placed in class B.
What if I want to refer to super multiple times?
Just write a template in B.doSomething() like this:
#Override
public void doSomething(String s) {
super.doSomething1(s);
c.doSomethingAfter1(s);
super.doSomething2(s);
c.doSomethingAfter2(s);
}
Of course, you have to modify interface C to include doSomethingAfter1() and doSomethingAfter2().
How to compile and run the code?
$ mkdir classes
$
$
$
$ javac -cp src -d classes src/Main.java
$ java -cp classes Main
packageA.A not found. Go without it!
$
$
$
$ javac -cp src -d classes src/packageB/B.java
$ java -cp classes Main
This is from packageA.A: World
This is from anonymous inner class: Hello
In the first run, the class packageB.B is not compiled (since Main.java does not have any reference to it). In the second run, the class is explicitly compiled, and thus you get the result you expected.
To help you fitting my solution to your problem, here is a link to the correct way to set the Nimbus Look and Feel:
Nimbus Look and Feel
You can use Class class to do that.
I.E.:
Class c = Class.forName("your.package.YourClass");
The sentence above will throw a ClassNotFoundException if not found on current classpath. If the exception is not thrown, then you can use newInstance() method in c to create objects of your.package.YourClass class. If you need to call a specific constructor, you can use getConstructors method to get one and use it to create a new instance.
Erm, can't you put the class you want to extend into the compile time class path, write your subclass as usual, and at runtime, explicitly trigger loading the subclass, and handle any exception thrown by the linker that indicates that the superclass is missing?

Resources