View Javadoc
1   /*
2    * The contents of this file are subject to the terms of the Common Development and
3    * Distribution License (the License). You may not use this file except in compliance with the
4    * License.
5    *
6    * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
7    * specific language governing permission and limitations under the License.
8    *
9    * When distributing Covered Software, include this CDDL Header Notice in each file and include
10   * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
11   * Header, with the fields enclosed by brackets [] replaced by your own identifying
12   * information: "Portions copyright [year] [name of copyright owner]".
13   *
14   * Copyright 2016 ForgeRock AS.
15   */
16  
17  package org.forgerock.json.resource;
18  
19  import org.forgerock.api.annotations.Create;
20  import org.forgerock.api.annotations.Delete;
21  import org.forgerock.api.annotations.Patch;
22  import org.forgerock.api.annotations.Query;
23  import org.forgerock.api.annotations.Read;
24  import org.forgerock.api.annotations.RequestHandler;
25  import org.forgerock.api.annotations.Update;
26  import org.forgerock.api.models.ApiDescription;
27  import org.forgerock.http.ApiProducer;
28  import org.forgerock.services.context.Context;
29  import org.forgerock.services.descriptor.Describable;
30  import org.forgerock.util.promise.Promise;
31  
32  /**
33   * Exposes an annotated POJO as an instance {@link org.forgerock.json.resource.RequestHandler} by looking for annotated
34   * and/or conventionally-named methods (as per {@link RequestHandler}).
35   * {@see org.forgeock.json.resource.annotations}
36   */
37  class AnnotatedRequestHandler implements org.forgerock.json.resource.RequestHandler,
38          Describable<ApiDescription, Request> {
39  
40      private final AnnotatedMethod createMethod;
41      private final AnnotatedMethod readMethod;
42      private final AnnotatedMethod updateMethod;
43      private final AnnotatedMethod deleteMethod;
44      private final AnnotatedMethod patchMethod;
45      private final AnnotatedMethod queryMethod;
46      private final AnnotatedActionMethods actionMethods;
47      private final Describable<ApiDescription, Request> describable;
48  
49      AnnotatedRequestHandler(Object requestHandler) {
50          if (!requestHandler.getClass().isAnnotationPresent(RequestHandler.class)) {
51              throw new IllegalArgumentException("RequestHandler missing from class: "
52                      + requestHandler.getClass().getName());
53          }
54          this.createMethod = AnnotatedMethod.findMethod(requestHandler, Create.class, false);
55          this.readMethod = AnnotatedMethod.findMethod(requestHandler, Read.class, false);
56          this.updateMethod = AnnotatedMethod.findMethod(requestHandler, Update.class, false);
57          this.deleteMethod = AnnotatedMethod.findMethod(requestHandler, Delete.class, false);
58          this.patchMethod = AnnotatedMethod.findMethod(requestHandler, Patch.class, false);
59          this.queryMethod = AnnotatedMethod.findMethod(requestHandler, Query.class, false);
60          this.actionMethods = AnnotatedActionMethods.findAll(requestHandler, false);
61          this.describable = requestHandler instanceof Describable
62                  ? (Describable<ApiDescription, Request>) requestHandler
63                  : null;
64      }
65  
66      @Override
67      public Promise<ResourceResponse, ResourceException> handleRead(Context context, ReadRequest request) {
68          return readMethod.invoke(context, request);
69      }
70  
71      @Override
72      public Promise<ResourceResponse, ResourceException> handleUpdate(Context context, UpdateRequest request) {
73          return updateMethod.invoke(context, request);
74      }
75  
76      @Override
77      public Promise<ResourceResponse, ResourceException> handlePatch(Context context, PatchRequest request) {
78          return patchMethod.invoke(context, request);
79      }
80  
81      @Override
82      public Promise<QueryResponse, ResourceException> handleQuery(Context context, QueryRequest request,
83              QueryResourceHandler handler) {
84          return queryMethod.invoke(context, request, handler);
85      }
86  
87      @Override
88      public Promise<ActionResponse, ResourceException> handleAction(Context context, ActionRequest request) {
89          return actionMethods.invoke(context, request);
90      }
91  
92      @Override
93      public Promise<ResourceResponse, ResourceException> handleCreate(Context context, CreateRequest request) {
94          return createMethod.invoke(context, request);
95      }
96  
97      @Override
98      public Promise<ResourceResponse, ResourceException> handleDelete(Context context, DeleteRequest request) {
99          return deleteMethod.invoke(context, request);
100     }
101 
102     @Override
103     public ApiDescription api(ApiProducer<ApiDescription> producer) {
104         if (describable == null) {
105             throw new UnsupportedOperationException(
106                     "The provided request handler does not support API Descriptor methods");
107         }
108         return describable.api(producer);
109     }
110 
111     @Override
112     public ApiDescription handleApiRequest(Context context, Request request) {
113         if (describable == null) {
114             throw new UnsupportedOperationException(
115                     "The provided request handler does not support API Descriptor methods");
116         }
117         return describable.handleApiRequest(context, request);
118     }
119 
120     @Override
121     public void addDescriptorListener(Listener listener) {
122         if (describable != null) {
123             describable.addDescriptorListener(listener);
124         }
125     }
126 
127     @Override
128     public void removeDescriptorListener(Listener listener) {
129         if (describable != null) {
130             describable.removeDescriptorListener(listener);
131         }
132     }
133 }