Overriding isBinaryContent() method in CXF LoggingOutInterceptor - java

I need to extend the Content Types CXF uses to check for binary data, and came across this answer:
Stop Apache CXF logging binary data of MultipartBody attachments
However, when I try to implement the override of isBinaryData() method:
#Override
public boolean isBinaryContent(String contentType) {
return contentType != null && BINARY_CONTENT_MEDIA_TYPES.contains(contentType) || "myContentType".equals(contentType);
}
I get an error accessing BINARY_CONTENT_MEDIA_TYPES:
The field AbstractLoggingInterceptor.BINARY_CONTENT_MEDIA_TYPES is not
visible
In the CXF implementation, this BINARY_CONTENT_MEDIA_TYPES is implemented through a static block as shown in the question referenced at the start. Do I simply just re-declare this List:
private static final List<String> BINARY_CONTENT_MEDIA_TYPES;
static {
BINARY_CONTENT_MEDIA_TYPES = new ArrayList<String>();
BINARY_CONTENT_MEDIA_TYPES.add("application/octet-stream");
BINARY_CONTENT_MEDIA_TYPES.add("image/png");
BINARY_CONTENT_MEDIA_TYPES.add("image/jpeg");
BINARY_CONTENT_MEDIA_TYPES.add("image/gif");
}
If so, I could just add another entry into the List with my required content type.

The field BINARY_CONTENT_MEDIA_TYPES is private and is not accessible from subclasses. The answer in the linked question may have been from an earlier version of CXF, where the list were not private.
As you say you can redeclare the list with your content type also in it. You can also append your logic to the existing logic in the parent implementation:
#Override
protected boolean isBinaryContent(String type)
{
return super.isBinaryContent(type) || "myContentType".equals(type);
}
If future versions of CXF alters the BINARY_CONTENT_MEDIA_TYPES list, this implementation automatically inherit those changes. While if the list is copied, then you manually have to change your implementation.

Related

Can an `ElementVisitor` be used to traverse the statements in the body of a method?

I'm trying to make a custom annotation that checks to see if a certain method is called in a method's body annotated with it. Something like:
#TypeQualifierDefault(ElementType.METHOD)
#Retention(RetentionPolicy.SOURCE)
#interface MutatingMethod {
}
interface Mutable {
void preMutate();
void postMutate();
// other methods
}
And then within a certain Mutable class we would have:
class Structure<T> implements Mutable {
#MutatingMethod
void add(T data) {
preMutate();
// actual mutation code
postMutate();
}
}
I want to be able to get warnings of some sort if the body of a method like add that is annotated with #MutatingMethod does not include calls to preMutate and postMutate. Can an ElementVisitor (javax.lang.model.element.ElementVisitor) be used to traverse the (possibly obfuscated) statements and method calls in the body of a method? If so what would that look like? If not what else can I use?
Just to clarify, I know this is impossible (or more difficult) to accomplish in runtime via bytecode decompilation, so this annotation is meant to only work during compilation via reflection (java.lang.reflect.* and javax.lang.model.*) and is not retained in class files.
You are free to modify the code however you want to get it to work, for example by introducing a new annotation called #MutableType that Structure and any other Mutable types must be annotated with it for this to work.
A cherry on top would be to assert that preMutate is called before postMutate and not after.
It shouldn't matter but I'm using Gradle and the IntelliJ IDEA IDE.
Any help is greatly appreciated; material on this is strangely scarce and/or inadequate on the web. I have been using publicly available sources to learn about this!
There are two modules,
java.compiler which contains the API for annotation processors and the simple abstraction you have already discovered.
The ElementVisitor abstraction does not support digging into the method’s code.
The jdk.compiler module, containing an extended API originally not considered to be part of the standard API and hence not included in the official API documentation prior to the introduction of the module system.
This API allows analyzing the syntax tree of the currently compiled source code.
When your starting point is an annotation processor, you should have a ProcessingEnvironment which was given to your init method. Then, you can invoke Trees.instance(ProcessingEnvironment) to get a helper object which has the method getTree(Element) you can use to get the syntax tree element. Then, you can traverse the syntax tree from there.
Most of these classes documented in the JDK 17 API do already exist in earlier versions (you might notice the “since 1.6”) even when not present in the older documentation. But prior to JDK 9 you have to include the lib/tools.jar of the particular JDK into your classpath when compiling the annotation processor.
(when writing a modular annotation processor)
import javax.annotation.processing.Processor;
module anno.proc.example {
requires jdk.compiler;
provides Processor with anno.proc.example.MyProcessor;
}
 
package anno.proc.example;
import java.util.*;
import javax.annotation.processing.*;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic;
import com.sun.source.tree.*;
import com.sun.source.tree.Tree.Kind;
import com.sun.source.util.Trees;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
#SupportedSourceVersion(SourceVersion.RELEASE_17) // adapt when using older version
#SupportedAnnotationTypes(MyProcessor.ANNOTATION_NAME)
public class MyProcessor extends AbstractProcessor {
static final String ANNOTATION_NAME = "my.example.MutatingMethod";
static final String REQUIRED_FIRST = "preMutate", REQUIRED_LAST = "postMutate";
// the inherited method does already store the processingEnv
// public void init(ProcessingEnvironment processingEnv) {
#Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
Optional<? extends TypeElement> o = annotations.stream()
.filter(e -> ANNOTATION_NAME.contentEquals(e.getQualifiedName())).findAny();
if(!o.isPresent()) return false;
TypeElement myAnnotation = o.get();
roundEnv.getElementsAnnotatedWith(myAnnotation).forEach(this::check);
return true;
}
private void check(Element e) {
Trees trees = Trees.instance(processingEnv);
Tree tree = trees.getTree(e);
if(tree.getKind() != Kind.METHOD) { // should not happen as compiler handles #Target
processingEnv.getMessager()
.printMessage(Diagnostic.Kind.ERROR, ANNOTATION_NAME + " only allowed at methods", e);
return;
}
MethodTree m = (MethodTree) tree;
List<? extends StatementTree> statements = m.getBody().getStatements();
if(statements.isEmpty() || !isRequiredFirst(statements.get(0))) {
processingEnv.getMessager()
.printMessage(Diagnostic.Kind.MANDATORY_WARNING,
"Mutating method does not start with " + REQUIRED_FIRST + "();", e);
}
// open challenges:
// - accept a return statement after postMutate();
// - allow a try { body } finally { postMutate(); }
if(statements.isEmpty() || !isRequiredLast(statements.get(statements.size() - 1))) {
processingEnv.getMessager()
.printMessage(Diagnostic.Kind.MANDATORY_WARNING,
"Mutating method does not end with " + REQUIRED_LAST + "();", e);
}
}
private boolean isRequiredFirst(StatementTree st) {
return invokes(st, REQUIRED_FIRST);
}
private boolean isRequiredLast(StatementTree st) {
return invokes(st, REQUIRED_LAST);
}
// check whether tree is an invocation of a no-arg method of the given name
private boolean invokes(Tree tree, String method) {
if(tree.getKind() != Kind.EXPRESSION_STATEMENT) return false;
tree = ((ExpressionStatementTree)tree).getExpression();
if(tree.getKind() != Kind.METHOD_INVOCATION) return false;
MethodInvocationTree i = (MethodInvocationTree)tree;
if(!i.getArguments().isEmpty()) return false; // not a no-arg method
ExpressionTree ms = i.getMethodSelect();
// TODO add support for explicit this.method()
return ms.getKind() == Kind.IDENTIFIER
&& method.contentEquals(((IdentifierTree)ms).getName());
}
}
Annotation processors only process declarations, not bytecode. They can not be used to make assertions about the content of a method.
If it is important to you that these methods are always called, you may want to enforce this with a proxy rather than having boilerplate code in each method. For instance, you could use a bytecode engineering library such as Javassist to add the calls at runtime:
var f = new ProxyFactory();
f.setSuperclass(Foo.class);
f.setFilter(m -> m.isAnnotationPresent(MutatingMethod.class));
Class c = f.createClass();
Foo foo = c.newInstance();
((Proxy)foo).setHandler((self, m, proceed, args) -> {
self.preMutate();
proceed.invoke(self, args);
self.postMutate();
});
foo.setName("Peter"); // automatically calls preMutate and postMutate()
(code untested, since I don't have an IDE at hand)
Then, the methods are always called in the proper order, as long as you control the creation of the objects in question (which you can sort of enforce by making the super class abstract).

How to structure email request class for different types of emails requiring different rendering params?

Currently, my notification request is like this:
public class EmailRequest{
public enum EmailType{
TYPE_1,
TYPE_2,
...
}
EmailType emailType;
String toAddress;
EmailRenderer renderer;
}
where EmailRenderer is an interface
public interface EmailRenderer{
EmailMessage render()
}
Now, each type of email has a separate implementation of the renderer interface and each implementation contains some rendering data that has to be provided by the client. This data can be different for each implementation.
Example:
public class Type1EmailRenderer implements EmailRenderer{
String param1;
String param2;
#Override
EmailMessage render(){
//rendering logic using the params
}
}
But, it seems redundant to me for the user to set the email type and renderer as well. Choosing the renderer should automatically get me the emailType. How should I restructure the request to be free of this redundancy? Also, can I use any design pattern for providing the renderers to my users?
I'll base my answer on a claim that,
putting aside programming-related questions, at the level of human logic, it looks to me strange that if I want to send an email I should know about renderers at all.
In my understanding If I have emails of different types (you've called them TYPE_1 and TYPE_2, let's give more "business" names for better clarity, like "dailyReport" or "advertisement", you'll see later why) I should just prepare a request with my data (param1, param2) and send it. I shouldn't care about renderers at all as long as the same email type assumes that the same type of renderer will be used.
So, lets say, type "advertisement" has a mandatory parameter String topic and optional parameter String targetAudience and type "dailyReport" has Integer totalUsersCount and optional String mostActiveUserName.
In this case, I propose the somewhat hybrid approach mainly based on Builder creation pattern:
public class EmailRequestBuilder {
private String toAddress;
private EmailRequestBuilder(String to) {
this.toAddress = to;
}
public static EmailRequestBuilder newEmailRequest(String to) {
return new EmailRequestBuilder(to);
}
public AdvertisementBuilder ofAdvertisementType(String topic) {
return new AdvertisementBuilder(topic, this);
}
public DailyReportBuilder ofDailyReportType(Integer totalUsersCount) {
return new DailyReportBuilder(totalUsersCount, this);
}
// all builders in the same package, hence package private build method,
// concrete email type builders will call this method, I'll show at the end
EmailRequest build(EmailType type, EmailRenderer emailRenderer) {
return new EmailRequest (to, type, emailRenderer);
}
}
public class AdvertisementBuilder {
private String topic;
private EmailRequestBuilder emailRequestBuilder;
// package private, so that only EmailRequestBuilder will be able to create it
AdvertisementBuilder(String topic, EmailRequestBuilder emailRequestBuilder) // mandatory parameters in constructor + reference to already gathered data {
this.topic = topic;
this.emailRequestBuilder = emailRequestBuilder;
}
// for optional parameters provide an explicit method that can be called
// but its not a mandatory call
public AdvertisementBuilder withTargetAudience(String audience) {
this.audience = audience;
return this;
}
public EmailRequest buildRequest() {
EmailRenderer renderer = new AdvertisementRenderer(topic, audience);
return emailRequestBuilder.build(EmailType.ADVERTISEMENT, renderer);
}
}
// A similar builder for DailyReport (I'll omit it but assume that there is a class
class DailyReportBuilder {}
Now the good part about it that now you can't go wrong as a user. A typical interaction with such a construction will be:
EmailRequest request = EmailRequestBuilder.newEmailRequest("john.smith#gmail.com")
.ofAdvertisementType("sample topic") // its a mandatory param, you have to supply, can't go wrong
.withTargetAudience("target audience") // non-mandatory call
.buildRequest();
Couple of notes:
Once you pick a type by calling ofDailyReportType/ ofAdvertisementType the user can't really supply parameters of different email type, because it gets "routed" to the builder that doesn't have methods for wrong parameters. An immediate implication of this is that an autocomplete will work in your IDE and people who will use this method will thank you about it ;)
It's easy to add new email types this way, no existing code will change.
Maybe with this approach, an enum EmailType will be redundant. I've preserved it in my solution but probably you'll drop it if it's not required.
Since I sometimes restrict the visibility (package private build methods, constructors, and so forth) - it will be __the_only__way to create the request which means that no-one will create "internal" objects only because it's possible to do so. At least a malicious programmer will think twice before breaking encapsulation :)
For example you can use "factory method".
EmailRenderer createRenderer(EmailType type) {
switch (type) {
case: TYPE_1:
return new RendererType1();
case: TYPE_2:
return new RendererType2();
...
}
}
Also, you probably can introduce cashing of this objects in order not to create them every time. Maybe some lazy initialization (you create appropriate Renderer first time when you needed and after that always return that same instance).

Omit wrapper tags in JAXB when the collection is empty

In JAXB, you can use the #XmlElementWrapper attribute to specify tags to wrap a collection of elements. However, these wrapper tags appear even if the collection is empty (they don't appear if the collection is null). Is there any way to have JAXB omit the wrapper tags if the collection is empty? Using adapters on the collection doesn't seem to work, since JAXB interprets this to mean it should apply the adapter to each element in the collection.
You can enforce your desired behavior in a somewhat hackish way by using
Marshal Event Callbacks.
#XmlRootElement(name="example")
#XmlAccessorType(XmlAccessType.FIELD)
public class Example {
#XmlElementWrapper(name="wrapper")
#XmlElement(name="item")
private List<Item> items;
// invoked by Marshaller before marshalling
private void beforeMarshal(Marshaller marshaller) {
if (items != null && items.isEmpty())
items = null;
}
// ... getters and setters
}
As described in Marshal Event Callbacks
there are actually 2 alternative ways how to use marshal callbacks:
Put the beforeMarshal and/or afterMarshal method directly into your class, and that's it. (This is the simpler way, and that's why I used this in my answer).
Create a Marshaller.Listener and write the beforeMarshal and afterMarshal methods there. You would then need to register this listener in your Marshaller.
You can use listener mechanism of Marshaller
You can add/set a listener like below :
jaxbMarshaller.setListener( new Listener()
{
#Override
public void beforeMarshal(Object source)
{
if ( source instanceof MyCollectionWrapper )
{
MyCollectionWrapper wrapper = (MyCollectionWrapper)source;
if ( wrapper.getCollection() != null && wrapper.getCollection().isEmpty() )
{
wrapper.setCollection( null );
}
}
}
});
where MyCollectionWrapper is the class representing your wrapper class.
This should remove the wrapper tag when the collection is empty.

Exposing hypermedia links on collection even it's empty using Spring Data Rest

First at all I read the previous question: Exposing link on collection entity in spring data REST
But the issue still persist without trick.
Indeed if I want to expose a link for a collections resources I'm using the following code:
#Component
public class FooProcessor implements ResourceProcessor<PagedResources<Resource<Foo>>> {
private final FooLinks fooLinks;
#Inject
public FooProcessor(FooLinks fooLinks) {
this.FooLinks = fooLinks;
}
#Override
public PagedResources<Resource<Foo>> process(PagedResources<Resource<Foo>> resource) {
resource.add(fooLinks.getMyCustomLink());
return resource;
}
}
That works correctly except when collection is empty...
The only way to works is to replace my following code by:
#Component
public class FooProcessor implements ResourceProcessor<PagedResources> {
private final FooLinks fooLinks;
#Inject
public FooProcessor(FooLinks fooLinks) {
this.FooLinks = fooLinks;
}
#Override
public PagedResources process(PagedResources resource) {
resource.add(fooLinks.getMyCustomLink());
return resource;
}
}
But by doing that the link will be exposed for all collections.
I can create condition for exposing only for what I want but I don't think is clean.
I think spring does some magic there trying to discover the type of the collection - on an empty collection you cannot tell which type it is of - so spring-data-rest cannot determine which ResourceProcessor to use.
I think I have seen in
org.springframework.data.rest.webmvc.ResourceProcessorHandlerMethodReturnValueHandler.ResourcesProcessorWrapper#isValueTypeMatch that they try to determine the type by looking at the first element in the collection and otherwise just stop processing:
if (content.isEmpty()) {
return false;
}
So I think you cannot solve this using spring-data-rest. For your controller you could fall back to writing a custom controller and use spring hateoas and implement your own ResourceAssemblerSupport to see the link also on empty collections.

Picketlink: How to get annotation parameters and the name of the function decorated when using #Secures?

I'm trying to define and use a custom security binding type called BasicRolesAllowed, as has been demonstrated in the Picketlink quickstarts here.
The only different between my type the ones in the quickstart, is that my annotation has to accept an array of strings (we want to secure methods using not just one but possibly combinations of roles), and thus my annotation is defined thus:
public #interface BasicRolesAllowed {
String[] value() default {};
}
Following the quickstart, I've tried to define how this decorator authenticates as such:
#Secures
#BasicRolesAllowed
public boolean doAdminCheck(Identity identity, IdentityManager identityManager, RelationshipManager relationshipManager) throws Exception {
/*
Sample usage of #BasicRolesAllowed is like:
#BasicRolesAllowed(value = RoleConstants.CREATE_USER)
TODO: need to get these from the #BasicRolesAllowed annotation instance/usage
*/
String[] requiredRoles = {};// get these from annotation
boolean isAuthorized = true;
for (String role : requiredRoles)
isAuthorized = isAuthorized && hasRole(relationshipManager, identity.getAccount(), getRole(identityManager, role));
return isAuthorized;
}
And as can be seen in the snippet, the trick part is:
String[] requiredRoles = {};// get these from annotation
How do I get the string constants passed to the annotation on the decorated method so I can use them in looking up roles?
Some Hints:
There's an answer to a similar question here, but the problem is that in that solution; one needs to know the name of the decorated function or class - which in my case is impossible given that the decorator will be used just about anywhere, and I don't know how to get these via the method shown in the Picketlink quickstart.
Also, the solution only shows how to obtain the value passed to an annotation expecting only 1 string - maybe I could try using values(), but the above limitation still stands in my way.
Thanks in advance to anyone who can help.
Thanks to #pedroigor over at #picketlink (freenode), the solution can be gleaned from an example of such a use-case in the picketlink quickstart here. In that file, a method getAnnotation() is defined, which has the signature:
private <T extends Annotation> T getAnnotation(InvocationContext invocationContext, Class<T> annotationType)
So, using this method, I'm able to introspect and obtain the values passed to my annotation as can be seen in my new implementation of the roles checking method here:
#Secures
#BasicRolesAllowed
public boolean hasBasicRolesCheck(InvocationContext invocationContext, Identity identity, IdentityManager identityManager, RelationshipManager relationshipManager) throws Exception {
BasicRolesAllowed basicRolesAllowed = getAnnotation(invocationContext,BasicRolesAllowed.class);
String[] requiredRoles = basicRolesAllowed.value();// get these from annotation
boolean isAuthorized = true;
for (String role : requiredRoles)
isAuthorized = isAuthorized && hasRole(relationshipManager, identity.getAccount(), getRole(identityManager, role));
return isAuthorized;
}
The essential modifications being:
I had to pass an instance of the invocation context InvocationContext invocationContext by adding this as a parameter to my method definition (CDI magic takes care of all else I hear).
I then obtain the annotation instance by calling:
BasicRolesAllowed basicRolesAllowed = getAnnotation(invocationContext,BasicRolesAllowed.class);
And then get the values/parameters passed to the annotation thus:
String[] requiredRoles = basicRolesAllowed.value();// get these from annotation
This solves my problem :-)

Categories