-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Java: Update JAX-RS annotation inheritance #18137
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -147,6 +147,20 @@ private predicate hasPathAnnotation(Annotatable annotatable) { | |
| ) | ||
| } | ||
|
|
||
| /** | ||
| * Holds if the class inherites the JaxRs `@Path` annotation. | ||
| */ | ||
| private predicate hasOrInheritsPathAnnotation(Class c) { | ||
| hasPathAnnotation(c) | ||
| or | ||
| // Note that by the JAX-RS spec, JAX-RS annotations on classes and interfaces | ||
| // are not inherited, but some implementations, like Apache CXF, do inherit | ||
| // them. I think this only applies if there are no JaxRS annotations on the | ||
| // class itself. | ||
|
||
| hasPathAnnotation(c.getAnAncestor()) and | ||
| not exists(c.getAnAnnotation().(JaxRSAnnotation)) | ||
| } | ||
|
|
||
| /** | ||
| * A method which is annotated with one or more JaxRS resource type annotations e.g. `@GET`, `@POST` etc. | ||
| */ | ||
|
|
@@ -191,7 +205,7 @@ class JaxRsResourceMethod extends Method { | |
| class JaxRsResourceClass extends Class { | ||
| JaxRsResourceClass() { | ||
| // A root resource class has a @Path annotation on the class. | ||
| hasPathAnnotation(this) | ||
| hasOrInheritsPathAnnotation(this) | ||
| or | ||
| // A sub-resource | ||
| exists(JaxRsResourceClass resourceClass, Method method | | ||
|
|
@@ -227,7 +241,7 @@ class JaxRsResourceClass extends Class { | |
| /** | ||
| * Holds if this class is a "root resource" class | ||
| */ | ||
| predicate isRootResource() { hasPathAnnotation(this) } | ||
| predicate isRootResource() { hasOrInheritsPathAnnotation(this) } | ||
|
|
||
| /** | ||
| * Gets a `Constructor` that may be called by a JaxRS container to construct this class reflectively. | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,162 @@ | ||
| import java.io.InputStream; | ||
| import java.io.IOException; | ||
| import java.lang.annotation.Annotation; | ||
| import java.lang.reflect.Type; | ||
| import jakarta.ws.rs.GET; | ||
| import jakarta.ws.rs.POST; | ||
| import jakarta.ws.rs.DELETE; | ||
| import jakarta.ws.rs.PUT; | ||
| import jakarta.ws.rs.OPTIONS; | ||
| import jakarta.ws.rs.HEAD; | ||
| import jakarta.ws.rs.Path; | ||
| import jakarta.ws.rs.BeanParam; | ||
| import jakarta.ws.rs.CookieParam; | ||
| import jakarta.ws.rs.FormParam; | ||
| import jakarta.ws.rs.HeaderParam; | ||
| import jakarta.ws.rs.MatrixParam; | ||
| import jakarta.ws.rs.PathParam; | ||
| import jakarta.ws.rs.Produces; | ||
| import jakarta.ws.rs.QueryParam; | ||
| import jakarta.ws.rs.client.Client; | ||
| import jakarta.ws.rs.core.Context; | ||
| import jakarta.ws.rs.core.MediaType; | ||
| import jakarta.ws.rs.core.MultivaluedMap; | ||
| import jakarta.ws.rs.core.Response; | ||
| import jakarta.ws.rs.ext.MessageBodyReader; | ||
|
|
||
| class ExtendsJakartaRs3 extends JakartaRs3 { // $ RootResourceClass | ||
| @Override | ||
| public int Get() { // $ ResourceMethod | ||
| return 1; | ||
| } | ||
|
|
||
| @Override | ||
| public @QueryParam("") // $ InjectionAnnotation | ||
| void Post() { | ||
| } | ||
|
|
||
| @Override | ||
| public double Delete() { // $ ResourceMethod=application/json | ||
| return 1.0; | ||
| } | ||
|
|
||
| @Override | ||
| public void Put() { // $ ResourceMethod=text/html | ||
| } | ||
|
|
||
| @Produces("application/json") // $ ProducesAnnotation=application/json | ||
| @Override | ||
| public void Options() { // not a resource method because it has a jax-rs annotation, so it doesn't inherit any jax-rs annotations | ||
| } | ||
|
|
||
| @Produces(MediaType.TEXT_XML) // $ ProducesAnnotation=text/xml | ||
| @Override | ||
| public void Head() { // not a resource method because it has a jax-rs annotation, so it doesn't inherit any jax-rs annotations | ||
| } | ||
|
|
||
| } | ||
|
|
||
| @Produces(MediaType.TEXT_XML) // $ ProducesAnnotation=text/xml | ||
| class ExtendsJakartaRs3WithProducesAnnotation extends JakartaRs3 { // Not a root resource class because it has a JAX-RS annotation | ||
| @Override | ||
| public int Get() { // $ ResourceMethod=text/xml | ||
| return 2; | ||
| } | ||
|
|
||
| @Override | ||
| public @QueryParam("") // $ InjectionAnnotation | ||
| void Post() { | ||
| } | ||
|
|
||
| @Override | ||
| public double Delete() { // $ ResourceMethod=application/json | ||
| return 2.0; | ||
| } | ||
|
|
||
| @Override | ||
| public void Put() { // $ ResourceMethod=text/html | ||
| } | ||
|
|
||
| @Override | ||
| public void Options() { // $ ResourceMethod=text/xml | ||
| } | ||
| } | ||
|
|
||
| @Path("") | ||
| public class JakartaRs3 implements JakartaRsInterface { // $ RootResourceClass | ||
| public JakartaRs3() { // $ InjectableConstructor | ||
| } | ||
|
|
||
| @Override | ||
| public int Get() { // $ ResourceMethod ResourceMethodOnResourceClass | ||
| return 1; // $ XssSink | ||
| } | ||
|
|
||
| @Override | ||
| public void Post() { // $ ResourceMethod ResourceMethodOnResourceClass | ||
| } | ||
|
|
||
| @Produces("application/json") // $ ProducesAnnotation=application/json | ||
| @Override | ||
| public double Delete() { // not a resource method because it has a jax-rs annotation, so it doesn't inherit any jax-rs annotations | ||
| return 1.0; | ||
| } | ||
|
|
||
| @Produces(MediaType.TEXT_HTML) // $ ProducesAnnotation=text/html | ||
| @Override | ||
| public void Put() { // not a resource method because it has a jax-rs annotation, so it doesn't inherit any jax-rs annotations | ||
| } | ||
|
|
||
| @Override | ||
| public void Options() { // $ ResourceMethod ResourceMethodOnResourceClass | ||
| } | ||
|
|
||
| @Override | ||
| public void Head() { // $ ResourceMethod ResourceMethodOnResourceClass | ||
| } | ||
|
|
||
|
|
||
| @Path("") | ||
| NonRootResourceClassJakarta subResourceLocator() { // $ SubResourceLocator | ||
| return null; | ||
| } | ||
|
|
||
| public class NonRootResourceClassJakarta { // $ NonRootResourceClass | ||
| @GET | ||
| int Get() { // $ ResourceMethod ResourceMethodOnResourceClass | ||
| return 0; // $ XssSink | ||
| } | ||
|
|
||
| @Produces("text/html") // $ ProducesAnnotation=text/html | ||
| @POST | ||
| boolean Post() { // $ ResourceMethod=text/html ResourceMethodOnResourceClass | ||
| return false; // $ XssSink | ||
| } | ||
|
|
||
| @Produces(MediaType.TEXT_PLAIN) // $ ProducesAnnotation=text/plain | ||
| @DELETE | ||
| double Delete() { // $ ResourceMethod=text/plain ResourceMethodOnResourceClass | ||
| return 0.0; | ||
| } | ||
|
|
||
| @Path("") | ||
| AnotherNonRootResourceClassJakarta subResourceLocator1() { // $ SubResourceLocator | ||
| return null; | ||
| } | ||
|
|
||
| @GET | ||
| @Path("") | ||
| NotAResourceClass1Jakarta NotASubResourceLocator1() { // $ ResourceMethod ResourceMethodOnResourceClass | ||
| return null; // $ XssSink | ||
| } | ||
|
|
||
| @GET | ||
| NotAResourceClass2Jakarta NotASubResourceLocator2() { // $ ResourceMethod ResourceMethodOnResourceClass | ||
| return null; // $ XssSink | ||
| } | ||
|
|
||
| NotAResourceClass2Jakarta NotASubResourceLocator3() { | ||
| return null; | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,106 @@ | ||||||||||||||||||||||
| import java.io.InputStream; | ||||||||||||||||||||||
| import java.io.IOException; | ||||||||||||||||||||||
| import java.lang.annotation.Annotation; | ||||||||||||||||||||||
| import java.lang.reflect.Type; | ||||||||||||||||||||||
| import jakarta.ws.rs.GET; | ||||||||||||||||||||||
| import jakarta.ws.rs.POST; | ||||||||||||||||||||||
| import jakarta.ws.rs.DELETE; | ||||||||||||||||||||||
| import jakarta.ws.rs.PUT; | ||||||||||||||||||||||
| import jakarta.ws.rs.OPTIONS; | ||||||||||||||||||||||
| import jakarta.ws.rs.HEAD; | ||||||||||||||||||||||
| import jakarta.ws.rs.Path; | ||||||||||||||||||||||
| import jakarta.ws.rs.BeanParam; | ||||||||||||||||||||||
| import jakarta.ws.rs.CookieParam; | ||||||||||||||||||||||
| import jakarta.ws.rs.FormParam; | ||||||||||||||||||||||
| import jakarta.ws.rs.HeaderParam; | ||||||||||||||||||||||
| import jakarta.ws.rs.MatrixParam; | ||||||||||||||||||||||
| import jakarta.ws.rs.PathParam; | ||||||||||||||||||||||
| import jakarta.ws.rs.Produces; | ||||||||||||||||||||||
| import jakarta.ws.rs.QueryParam; | ||||||||||||||||||||||
| import jakarta.ws.rs.client.Client; | ||||||||||||||||||||||
| import jakarta.ws.rs.core.Context; | ||||||||||||||||||||||
| import jakarta.ws.rs.core.MediaType; | ||||||||||||||||||||||
| import jakarta.ws.rs.core.MultivaluedMap; | ||||||||||||||||||||||
| import jakarta.ws.rs.core.Response; | ||||||||||||||||||||||
| import jakarta.ws.rs.ext.MessageBodyReader; | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // This is not a resource class because it doesn't have a @Path annotation. | ||||||||||||||||||||||
| // Note that inheritance of class or interface annotations is not supported in | ||||||||||||||||||||||
| // JAX-RS. | ||||||||||||||||||||||
| public class JakartaRs4 implements JakartaRsInterface { // $ RootResourceClass | ||||||||||||||||||||||
|
||||||||||||||||||||||
| // This is not a resource class because it doesn't have a @Path annotation. | |
| // Note that inheritance of class or interface annotations is not supported in | |
| // JAX-RS. | |
| public class JakartaRs4 implements JakartaRsInterface { // $ RootResourceClass | |
| // By the JAX-RS spec, this is not a resource class because it doesn't | |
| // have a @Path annotation. Inheritance of class or interface annotations | |
| // is not supported in JAX-RS. However, this is a resource class for some | |
| // implementations, like Apache CXF, that allow inheritance of JAX-RS | |
| // annotations. | |
| public class JakartaRs4 implements JakartaRsInterface { // $ RootResourceClass |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| import java.io.InputStream; | ||
| import java.io.IOException; | ||
| import java.lang.annotation.Annotation; | ||
| import java.lang.reflect.Type; | ||
| import jakarta.ws.rs.GET; | ||
| import jakarta.ws.rs.POST; | ||
| import jakarta.ws.rs.DELETE; | ||
| import jakarta.ws.rs.PUT; | ||
| import jakarta.ws.rs.OPTIONS; | ||
| import jakarta.ws.rs.HEAD; | ||
| import jakarta.ws.rs.Path; | ||
| import jakarta.ws.rs.BeanParam; | ||
| import jakarta.ws.rs.CookieParam; | ||
| import jakarta.ws.rs.FormParam; | ||
| import jakarta.ws.rs.HeaderParam; | ||
| import jakarta.ws.rs.MatrixParam; | ||
| import jakarta.ws.rs.PathParam; | ||
| import jakarta.ws.rs.Produces; | ||
| import jakarta.ws.rs.QueryParam; | ||
| import jakarta.ws.rs.client.Client; | ||
| import jakarta.ws.rs.core.Context; | ||
| import jakarta.ws.rs.core.MediaType; | ||
| import jakarta.ws.rs.core.MultivaluedMap; | ||
| import jakarta.ws.rs.core.Response; | ||
| import jakarta.ws.rs.ext.MessageBodyReader; | ||
|
|
||
| @Path("/resource") // This annotation has no effect, as class/interface annotations are not inherited in jax-rs | ||
owen-mc marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| public interface JakartaRsInterface { | ||
| @GET | ||
| int Get(); // $ ResourceMethod | ||
|
|
||
| @POST | ||
| void Post(); // $ ResourceMethod | ||
|
|
||
| @DELETE | ||
| double Delete(); // $ ResourceMethod | ||
|
|
||
| @PUT | ||
| void Put(); // $ ResourceMethod | ||
|
|
||
| @OPTIONS | ||
| void Options(); // $ ResourceMethod | ||
|
|
||
| @HEAD | ||
| void Head(); // $ ResourceMethod | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.