Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
How can you replace
java.io.File
for a given web application (running on a servlet container) for the following conditions
Given I have a class
class AmazonS3File extends java.io.File
Replace every
java.io.File
with
AmazonS3File
Replace every
java.io.File
with
AmazonS3File
but under the condition that the call came from a specific library, say
com.jetbrains
package (not sure if this is even theoretically possible)
However, here's the
pseudo
code I have:
new AgentBuilder.Default()
.with(AgentBuilder.Listener.StreamWriting.toSystemOut())
.with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
.type(ElementMatchers.is(java.io.File.class))
.transform((builder, typeDescription, classLoader, module) ->
new ByteBuddy().redefine(java.io.File.class).constructor(ElementMatchers.anyOf(AmazonS3File.class) /* <-- What to put here?*/))
.installOnByteBuddyAgent();
File videoFile = new File(OUTPUT_PATH);
System.out.println(videoFile.getPath());
What should be placed in the ByteBuddy().redefine(java.io.File.class).constructor
to make it load the constructor of AmazonS3File
instead?
–
–
–
–
Byte Buddy allows you to adjust library code by for example using a Java agent. A Java agent is notified on any class being loaded and using one, you can indeed replace any call to new File()
by your new AmazonS3File()
. To do so, you would need to transform all classes within a package where this in-code replacement is relevant. You would be using a MemberSubstitution
for this:
new AgentBuilder.Default()
.with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
.type(nameStartsWith("pkg.of.library."))
.transform((builder, typeDescription, classLoader, module) -> builder.visit(MemberSubstitution.strict()
.constructor(isDeclaredBy(File.class))
.replaceWith(MyFactory.class.getMethod("file", String.class))
.on(any()))
.installOnByteBuddyAgent();
To make this work, you will have to create some factory class MyFactory
that returns any instance of type File
where you can for example return your Amazon file if it exteds Java's File
.
The substitution basically says: for any type in the package and subpackages of pgk.of.library, scan any()
method or constructor for constructors of File
and replace them with a call to MyFactory::file
. For this to work, the factory must have the same arguments as the file constructor being replaced.
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.