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 2015-2016 ForgeRock AS.
15   */
16  
17  package org.forgerock.json.resource;
18  
19  import org.forgerock.api.annotations.Patch;
20  import org.forgerock.api.annotations.Read;
21  import org.forgerock.api.annotations.SingletonProvider;
22  import org.forgerock.api.annotations.Update;
23  import org.forgerock.api.models.ApiDescription;
24  import org.forgerock.http.ApiProducer;
25  import org.forgerock.services.context.Context;
26  import org.forgerock.services.descriptor.Describable;
27  import org.forgerock.util.promise.Promise;
28  
29  /**
30   * Exposes an annotated POJO as an instance {@link org.forgerock.json.resource.RequestHandler} by looking for annotated
31   * and/or conventionally-named methods (as per {@link SingletonProvider}).
32   * <p>
33   * This class handles the requests to singleton endpoints, so only Read, Update, Patch and Action are supported.
34   * are implemented - the remaining methods delegate to the {@link InterfaceSingletonHandler} for reporting the
35   * erroneous request to the caller.
36   * {@see org.forgeock.json.resource.annotations}
37   */
38  class AnnotatedSingletonHandler extends InterfaceSingletonHandler implements Describable<ApiDescription, Request> {
39  
40      private final AnnotatedMethod readMethod;
41      private final AnnotatedMethod updateMethod;
42      private final AnnotatedMethod patchMethod;
43      private final AnnotatedActionMethods actionMethods;
44      private final Describable<ApiDescription, Request> describable;
45  
46      public AnnotatedSingletonHandler(Object requestHandler) {
47          super(null);
48          if (!requestHandler.getClass().isAnnotationPresent(SingletonProvider.class)) {
49              throw new IllegalArgumentException("SingletonProvider missing from class: "
50                      + requestHandler.getClass().getName());
51          }
52          this.readMethod = AnnotatedMethod.findMethod(requestHandler, Read.class, false);
53          this.updateMethod = AnnotatedMethod.findMethod(requestHandler, Update.class, false);
54          this.patchMethod = AnnotatedMethod.findMethod(requestHandler, Patch.class, false);
55          this.actionMethods = AnnotatedActionMethods.findAll(requestHandler, false);
56          this.describable = requestHandler instanceof Describable
57                  ? (Describable<ApiDescription, Request>) requestHandler
58                  : null;
59      }
60  
61      @Override
62      public Promise<ResourceResponse, ResourceException> handleRead(Context context, ReadRequest request) {
63          return readMethod.invoke(context, request);
64      }
65  
66      @Override
67      public Promise<ResourceResponse, ResourceException> handleUpdate(Context context, UpdateRequest request) {
68          return updateMethod.invoke(context, request);
69      }
70  
71      @Override
72      public Promise<ResourceResponse, ResourceException> handlePatch(Context context, PatchRequest request) {
73          return patchMethod.invoke(context, request);
74      }
75  
76      @Override
77      public Promise<ActionResponse, ResourceException> handleAction(Context context, ActionRequest request) {
78          return actionMethods.invoke(context, request);
79      }
80  
81      @Override
82      public ApiDescription api(ApiProducer<ApiDescription> producer) {
83          if (describable == null) {
84              throw new UnsupportedOperationException(
85                      "The provided request handler does not support API Descriptor methods");
86          }
87          return describable.api(producer);
88      }
89  
90      @Override
91      public ApiDescription handleApiRequest(Context context, Request request) {
92          if (describable == null) {
93              throw new UnsupportedOperationException(
94                      "The provided request handler does not support API Descriptor methods");
95          }
96          return describable.handleApiRequest(context, request);
97      }
98  
99      @Override
100     public void addDescriptorListener(Listener listener) {
101         if (describable != null) {
102             describable.addDescriptorListener(listener);
103         }
104     }
105 
106     @Override
107     public void removeDescriptorListener(Listener listener) {
108         if (describable != null) {
109             describable.removeDescriptorListener(listener);
110         }
111     }
112 }