Modify library class at runtime - java/maven - java

I'm working on a Maven Plugin and I need to modify one class of an external jar (used during maven execution), to add:
a new field on this class
a getter for the field
some behavior to an existing setter to populate the field
The library code should use my 'new' class, and I want to be able to use the getter to retrieve some additional information.
Instances of this class are created within the library code (I'm not creating them in my code, I just need to access them).
Class is a non-final public class.
Do you know if this feasible and which is the best way to do it? Is it possible to do it with ByteBuddy?
EDIT: I cannot wrap the class, because it's not instantiated in my own code, let me elaborate a bit.
There's a library class named "Parser" that instantiate and populate some "Element" instances. My code looks like:
List<library.Element> elements = new library.Parser(file).parse();
the Parser.parse() method calls "Element.setProperties(List properties)" on each element.
I want to be able to enrich the setProperties method to store the original list of properties (that are lost otherwise)
Thanks
Giulio

At the end I managed to obtain the wanted result with byte-buddy (I don't know if it's the best solution but it works):
instrument library class (library.Element) using 'rebase' strategy to delegate the method 'setProperties' call to an interceptor.
Note: this must be done as the first instruction of the maven plugin execution when library.Element.class is not yet loaded (I didn't want to use a JVM agent)
define the above interceptor as a class that stores the original 'properties' value in a global map (key = identity hash code of the object, value = properties) and then call the original 'setProperties' method of library.Element
change my code to get properties from the map, instead of library.Element getter (I had already a wrapper of this class).
If someone is interested, I can show some code.

Your suggestion sounds a bit hackish, and in general what you want to do would not even be possible without generating sources from the JAR, modifying them, and then repackaging. If I faced this problem, I would consider using a decorator pattern instead. You can create a wrapper which exposes all the methods of your JAR, except it would add one extra field along with a getter and setter.
import com.giulio.old.jar.everything.*;
public class WrapperOfJar {
private String newField;
public String getNewField() { // ... }
public void setNewField() { // ... }
// all getters and setters from current JAR
}
Now your users will see the same interface, plus one new method for your field. This answer assumes that the class in question is not final.

Related

How to call the template method by two names in a Template Method Pattern

I'm doing this a bit backwards because I'm following a specific sequence of project instructions. I have two java classes. One of them simulates the grep function from Linux, and the other simulates the lineCount capability. I have them both implemented, but the NEXT step in the project is to create a superclass using the template method pattern that "will contain all fields and algorithms common to the other two programs".
There is a lot of common functionality between the two, and it is apparent what parts need to be part of the template and which need to be part of the implementations. For example, each of them needs to be able to create File objects based on the path string used to call the method, and search through the File's list method using a regex that is used to call the method. This is common functionality that should definitely be part of the template/abstract class.
It would be nice to be able to declare something like this:
public abstract class RegexCommands{
protected Variables;
public Map<things> myMethod(variables){
//common functionality which includes storing and using the variables
hookMethod(); //based on what you create in commonFunctionality
return resultAfterHookMethod;
}
}
public class Grep extends RegexCommands{
public hookMethod(){
class specific things;
}
}
public class lineCount extends RegexCommands{
public hookMethod(){
class specific things;
}
}
and just call it with
RegexCommands myObject = new Grep();
myObject.myMethod(variables);
and have it return what I'm looking for (grep command for the Grep object, lineCount for the LineCount object). However, the instructions specifically state that it will be called like so:
RegexCommands myObject = new Grep();
myObject.grep(variables);
RegexCommands myObject = new LineCount();
myObject.lineCount(variables);
and also that there are slight differences in the variables used. (lineCount doesn't need a substringSelectionPattern, for example) The way I have it set up now is that the hooked methods call super to their parent, and the template calls myMethod. This is obviously not the way that it is supposed to work. For one thing, it seems like I have had to introduce non-common methods to my template that just call the main template method, which means that one could, theoretically (although I haven't tested it), do something like
RegexCommands myObject = new LineCount();
myObject.grep(variables);
Which is not behavior that I want to allow and seems like it defeats the purpose of using the template. The other problem (that I have actually run into) is that my hookMethods don't seem to have access to the instance variables created in commonFunctionality (ie when I try to access a matcher that was created in commonFunctionality, it returns null even if I declare it as an instance variable instead of a method-level scope, like I would prefer).
So I'm kind of stuck and looking for some help. How do I have these objects use the myMethod pattern in the template without this terrible workaround that destroys the separateness of my objects, and how do I have the non-common methods use ArrayLists and/or Maps from the commonFunctionality without passing EVERYTHING over as parameters (which I have been advised not to do as it ruins the point of using templates)?
For one thing, it seems like I have had to introduce non-common methods to my template that just call the main template method,
Yes you would need to introduce such methods for your given requirement. But as you stated later that this would be incorrect as a LineCount object can call a grep method, this can be avoided by doing a instance of check in the non-common methods you would be writing. Doing the job if it fits the what is expected called or exiting otherwise.
For you original problem that you have run into
my hookMethods don't seem to have access to the instance variables created in commonFunctionality (ie when I try to access a matcher that was created in commonFunctionality, it returns null even if I declare it as an instance variable instead of a method-level scope, like I would prefer).
You can't define a abstract variable in java, the only legal modifier for variable in java are
public, protected, private, static, final, transient, volatile
you need to have a concrete implementation of commonFunctionality and you can have a getter method for it. You can define a abstract method for this in the abstract class. Refer to the answer of this post for more info Abstract variables in Java?
RegexCommands myObject = new Grep();
myObject.grep(variables);
RegexCommands myObject = new LineCount();
myObject.lineCount(variables);
This is only possible (in Java) if the interface/abstract class RegexCommands defines both methods. Thus both implementation needs to implement them, too. If you want to stick to that requirement you could do that and let Grep.lineCount() throw some exception.
A workaround could be to make RegexCommands to be a facade that only delegates method calls from RegexCommands.grep() to new Grep().myObject()
However, you should contact the requestor to clarify it.

force private member access from same class only through method in java

I want to force future users of a class to access a private member also from future code written in that class only through an accessor method (even through junit or anything like that).
is there a way to do it in java? can someone show an example if possible?
You cannot force to do that, but you can create a method and document that enforcement in the javadoc.
private int myMember;
/**
* ATTENTION: use this method instead of setting the member directly.
*/
public void setMyMember(int value) {
this.myMember = value;
}
Also, there is an alternative solution which might work. Use ThreadLocal, like this:
private final ThreadLocal<String> member = new ThreadLocal<String>();
public void setMember(final String value) {
member.set(value);
}
The member field is final and cannot be changed. Therefore, clients will be forced to call the setter directly.
As long as the field is part of the class, anyone can access it directly. This can be a problem when we try to force all (co-)authors to go through the getters/setters because those method do some conversion, checking or bookkeeping stuff. Like incrementing internal counters.
A general solution, that comes to mind: it could be possible by using annotations. You'd have to create an annotation (and the annotation processor code) to ensure, that it is a compile time error if the field is used outside of it's getter/setter method:
#GetterSetterAccessOnly
private int value;
If you want to prevent reflection you can use a SecurityManager. If this is not an option you can get the call stack with Thread.currentThread().getStackTrace() and check the caller is from your class.
Two problems with this are; the performance won't be great. Anything you can do in the method you can do externally so the simplest work around is to copy its contents without the check. ;)
I suggest you document your reason for not allowing access this way.
Make use of inheritance to hide the field:
Do your class with all the fields and getter/setters that you need. (You may make it abstract)
Do a child class, that inherits from the previews one, and since the field isn't accessible, you force the use of the getter/setter pair.
As you are talking about the accessing in the same class, they have all the freedom to access the private member directly as well as through accessor method if that member has. So basically you cannot prevent them using the member directly in the same class.
I am afraid there is no standard way to do that. If a user has access to a class instance, although a private member is declared private, permissions can be changed at runtime and accessed anyway.
You need a classloader that enforces permissions. You can make an OSGi Bundle and enforce a control policy over the instance of your objects exported as services through interfaces. However this will tie you to an OSGi container to run your application.
Well, if they have access to your code, they can do anything they want. In the worst case, they remove your getters and setters and just put in a public field instead ;)
But of course you can motivate them to not access the variable directly with an according design:
you should check whether the others should rather implement subclasses instead of changing the class itself. Then private fields are, of course, only accessed via setters and getters.
you could move the data into a different class, and use your getters and setters to access the data in the other class. Doing this just for the sake of not having the data directly in your class is maybe a bit counter-intuitive, but since you probably have a good reason why they shouldn't access that very data, it indicates a different responsibility. So refactoring to meet the SRP is a good idea anyways.

Java: Enforcing doubly linked objects

I am designing a game engine in Java.
At the core of this engine exist the two classes Asset and Attribute, where an Asset has a list of Attributes. Most Attributes need no link back up to their Attribute, meaning that Attributes can and often do appear in the lists of more than one Asset. However, there is an extention of Attribute called UniqueAttribute, which is an implementation for those that are specific to their Asset, and utilise a link back.
Ideally, my Asset's addAttribute method would look something like this if I cut out the other code:
public void addAttribute(Attribute attribute){
if(attribute instanceof UniqueAttribute)
((UniqueAttribute)attribute).setAsset(this);
attributeList.add(attribute);
}
Unfortunately, since they live in different packages, UniqueAttribute.setAsset() must be public. This leaves the method open to outside users of the engine to mess with, and while I could just handwave it off by saying using this method directly is a bug - it seems rather sloppy.
The second option is to provide the UniqueAttribute with the Asset on construction, meaning that the code at the point of creation would look something like this:
asset.addAttribute(new UniqueAttribute(asset));
While I can add a check-and-throwable or assert to confirm the correct asset is passed in, I am basically relying on the user to connect the two, which I also would prefer not to do.
The third option is to bite the bullet and put 50 java files all into the same package so that I can just use the standard visiblity.
Is there some kind of pattern or something that will help link these two together without exposing the wires, or forcing me to put everything into one massive package?
Irrelevant rant: I have always disliked that the concept of subpackages in java has not really been expanded in any meaningful way. A subpackage, as far as java is concerned is simply a different package, and there have been many occasions I could do with more visibility modifiers directly related to this.
My suggestion would be that Asset, Attribute and UniqueAttribute should all be in the same package (possibly along with a few other core "engine" classes). Then you can use standard package visibility for UniqueAttribute.setAsset.
You don't need to put all other classes in the same package - your Asset.addAttribute method should be public and accessible from other packages so the rest of your application can just use that directly.
So the solution could be called "3-" in your categorisation.
As some more general points, also consider:
Whether you really need the complexity of both Attributes and UniqueAttributes - I'm not sure you really do, having previously implemented a reasonably complex game object model without needing anything that looked like a UniqueAttribute. If the UniqueAttribute "needs a link back" then perhaps it is trying to be too clever / do too much?
Even if you do need both, do you really want to write code that treats them the same way / as part of the same object heirarchy? they seem quite conceptually different, and you will end up writing a lot of conditional code if you conflate the two.....
There are various other advantages of attributes being consistently shared and immutable - it's better for memory usage, concurrency and testability among other things. And as they are presumably quite small, the cost of copy-on-write semantics is trivial in the cases where you need it.
I would add a callback method in Attribute which is called when an instance of Attribute is added to an Asset:
class Attribute {
protected void addedToAsset(Asset asset) {
// do nothing
}
}
This method would be called in the addAttribute method
class Asset {
public void addAttribute(Attribute attribute) {
attributeList.add(attribute);
attribute.addedToAsset(this);
}
}
And the method would be overridden in UniqueAttribute in order to control the link with Asset:
class UniqueAttribute extends Attribute {
Asset asset;
protected void addedToAsset(Asset asset) {
// manage the previous link if needed
if (this.asset != null) { ... }
this.asset = asset;
}
}
Wit this solution, Asset and Attribute should be placed in the same package. But UniqueAttribute could be in whatever package you want.
Modify your scond option
asset.addAttribute(new UniqueAttribute(asset));
like this:
class UniqueAttribute {
Asset asset;
public UniqueAttribute(Asset asset) { this.asset = asset; asset.addAttribute(this); }
}
Do a similar approach for the non unique Attribute. That means instead of using addAttribute() from the outside, only use it inside of the constructors.
An other option is to add two factory methods to Asset: createAttribute() and createUniqueAttribute();
Well, basically you want to do 3 things:
make setAsset method visible inside the package containing Asset class
hide setAsset method from all other packages
don't use subpackages to achieve that
That's a bit problematic: if you declare public that method in Attribute class all other classes including that package (let's call it AttributePackage), you can't prevent the user to include somewhere that package.
On the other hand you could do the following:
create an interface containing only the Attribute method that user should use, let's call it AttributeInterface
make Attribute implement that interface
add AttributeInterface to a new package
An user that want use Attribute class should use it through AttributeInterface meanwhile
Asset will use Attribute class directly in order to have access to all methods.
I'll make an example:
//attribute interface package
public interface AttributeInterface{
public void publicAttributeMethodClientShouldUse();
}
//attribute package
public class Attribute{
public void setAsset(Asset a);
public void publicAttributeMethodClientShouldUse();
}
Asset will reference directly Attribute meanwhile user should reference AttributeInterface. Hope to be clear.
First, these entities do appear to be so closely related as to be placed in the same package. I'd put them in the same package and make the addAttribute method package-private.
Bear in mind though that since the introduction of AccessibleObject in Java, visibility and access control in the language has become merely cosmetic... Anyone using your library can grab your classes and make private methods and fields accessible and modifiable! Hell, they can even modify final members! So, don't put much emphasis in the visibility aspect and just make sure your model and method flow make sense for your users and work correctly.

Java Builder generator problem

In a project of mine I have two packages full of DTOs, POJOs with just getters and setters. While it's important that they are simple java beans (e.g. because Apache CXF uses them to create Web Service XSDs etc.), it's also awful and error-prone to program like that.
Foo foo = new Foo();
foo.setBar("baz");
foo.setPhleem(123);
return foo;
I prefer fluent interfaces and builder objects, so I use maven / gmaven to automatically create builders for the DTOs. So for the above code, a FooBuilder is automatically generated, which I can use like this:
Foo foo = new FooBuilder()
.bar("baz")
.phleem(123)
.build();
I also automatically generates Unit tests for the generated Builders. A unit test would generate both of the above codes (builder version and non builder version) and assert that both versions are equivalent in terms of equals() and hashcode(). The way I can achieve that is to have a globally accessible Map with defaults for every property type. Something like this:
public final class Defaults{
private Defaults(){}
private static final Map<Class<?>, Object> DEFAULT_VALUES =
new HashMap<Class<?>, Object>();
static{
DEFAULT_VALUES.put(String.class, "baz");
// argh, autoboxing is necessary :-)
DEFAULT_VALUES.put(int.class, 123);
// etc. etc.
}
public static getPropertyValue(Class<?> type){
return DEFAULT_VALUES.get(type);
}
}
Another non-trivial aspect is that the pojos sometimes have collection members. e.g.:
foo.setBings(List<Bing> bings)
but in my builder I would like this to generate two methods from this case: a set method and an add method:
fooBuilder.bings(List<Bing> bings); // set method
fooBuilder.addBing(Bing bing); // add method
I have solved this by adding a custom annotation to the property fields in Foo
#ComponentType(Bing.class)
private List<Bing> bings;
The builder builder (sic) reads the annotation and uses the value as the generic type of the methods to generate.
We are now getting closer to the question (sorry, brevity is not one of my merits :-)).
I have realized that this builder approach could be used in more than one project, so I am thinking of turning it into a maven plugin. I am perfectly clear about how to generate a maven plugin, so that's not part of the question (nor is how to generate valid Java source code). My problem is: how can I deal with the two above problems without introducing any common dependencies (between Project and Plugin):
<Question>
I need a Defaults class (or a similar mechanism) for getting default values for generated unit tests (this is a key part of the concept, I would not trust automatically generated builders if they weren't fully tested). Please help me come up with a good and generic way to solve this problem, given that each project will have it's own domain objects.
I need a common way of communicating generic types to the builder generator. The current annotation based version I am using is not satisfactory, as both project and plugin need to be aware of the same annotation.
</Question>
Any Ideas?
BTW: I know that the real key point of using builders is making objects immutable. I can't make mine immutable, because standard java beans are necessary, but I use AspectJ to enforce that neither set-methods nor constructors are called anywhere in my code base except in the builders, so for practical purposes, the resulting objects are immutable.
Also: Yes, I am aware of existing Builder-generator IDE plugins. That doesn't fit my purpose, I want an automated solution, that's always up to date whenever the underlying code has changed.
Matt B requested some info about how I generate my builders. Here's what I do:
I read a class per reflection, use Introspector.getBeanInfo(clazz).getPropertyDescriptors() to get an array of property descriptors. All my builders have a base class AbstractBuilder<T> where T would be Foo in the above case. Here's the code of the Abstract Builder class. For every property in the PropertyDescriptor array, a method is generated with the name of the property. This would be the implementation of FooBuilder.bar(String):
public FooBuilder bar(String bar){
setProperty("bar", bar);
return this;
}
the build() method in AbstractBuilder instantiates the object and assigns all properties in it's property map.
A POJO is an object which doesn't follow the Java Bean spoec. ie. it doesn't have setters/getters.
JavaBeans are not required to have setters, if you don't want them to be called, don't generate them. (Your builder can call a package local or private constructor to create your immutable objects)
Have you looked at Diezel ?
It's a Builder generator.
It handles generic types, so it might be helpful here for the question 2
It generates all the interfaces, and implementation boiler plate based on a description XML file. You might be able, through introspection to generate this XML (or even goes directly into lower API )
It is bundled as a maven plugin.

Java: What is the fastest way to inject fields using reflection?

Suppose, I have a lot of classes, which are constructed using Java reflection (for some reason). Now I need to post-inject values to fields, which are
annotated with #PostInject.
public class SomeClass {
#PostInject
private final String someString = null;
public void someMethod() {
// here, someString has a value.
}
}
My question is: what is a fast way to set a field using reflection?
Remember, I need to do this very often on a lot of classes, that's
why performance is relevant.
What I would do by intuition is shown by this pseudo-code:
get all fields of the class
clazz.getFields();
check, which are annotated with #PostInject
eachField.getAnnotation(PostInject.class);
make these fields accessible
eachAnnotatedField.setAccessible(true);
set them to a certain value
eachAnnotatedField.set(clazz, someValue);
I'm afraid that getting all fields is the slowest thing to do.
Can I someone get a field, when I know it from the beginning?
NOTE: I can't just let the classes implement some interface, which would
allow to set the fields using a method. I need POJOs.
NOTE2: Why I want post-field injection: From the point of view of an API user, it must be possible to use final fields. Furthermore, when the types and number of fields are not known by the API a priori, it is impossible to achieve field initialization using an interface.
NOTE2b: From the point of view of the user, the final contract is not broken. It stays final. First, a field gets initialized, then it can't be changed. By the way: there are a lot of APIs which use this concept, one of them is JAXB (part of the JDK).
How about doing steps 1 to 3 just after you constructed the object and saving the set of annotated fields that you obtain either in the object itself or by keeping a separate map of class to set-of-annotated-fields?
Then, when you need to update the injected fields in an object, retrieve the set from either the object or the seperate map and perform step 4.
Don't know if it's any good, but this project looks like it would do what you want. Quote:
A set of reflection utilities and
miscellaneous utilities related to
working with classes and their fields
with no dependencies which is
compatible with java 1.5 and generics.
The utilities cache reflection data
for high performance operation but
uses weak/soft caching to avoid
holding open ClassLoaders and causing
the caches to exist in memory
permanently. The ability to override
the caching mechanism with your own is
supported.
Another option, as you say you know the few fields concerned from the beginning, is to ask only for those fields or methods.
Example : see getDeclaredMethod or getDeclaredField in java/lang/Class.html
You can exploit existing frameworks that allow to inject dependencies on object construction. For example Spring allows to do that with aspectj weaving. The general idea is that you define bean dependencies at spring level and just mark target classes in order to advise their object creation. Actual dependency resolution logic is injected directly to the class byte-code (it's possible to use either compile- or load-time weaving).
Fastest way to do anything with reflection is to cache the actual Reflection API classes whenever possible. For example I very recently made a yet-another-dynamic-POJO-manipulator which I believe is one of those things everyone ends up doing at some point which enables me to do this:
Object o = ...
BeanPropertyController c = BeanPropertyController.of(o);
for (String propertyName : c.getPropertyNames()) {
if (c.access(propertyName) == null &&
c.typeOf(propertyName).equals(String.class)) {
c.mutate(propertyName, "");
}
}
The way it works is that it basically has that one controller object which lazyloads all the properties of the bean (note: some magic involved) and then reuses them as long as the actual controller object is alive. All I can say is that by just saving the Method objects themselves I managed to turn that thing into a damn fast thing and I'm quite proud of it and even considering releasing it assuming I can manage to sort out copyrights etc.

Categories

Resources